原根與指標,離散對數

原根:

  定義

設m是正整數,a是整數,若a mod m 的階等於\varphi (m),則稱a爲模m的一個原根(\varphi (m)表示m的歐拉函數)

當且僅當指數爲P - 1的時候,g^{p-1} \equiv 1 (mod\, p)成立,則質數P的原根即爲g

       求解方法:1.將p-1進行質因數分解 p-1=p_{1}^{a_1}p_{2}^{a_2}p_{3}^{a_3}.........p_{n}^{a_n}

                         2.枚舉i,並判斷對於每個i是否都有,第一個符合i的即是P                       的最小原根

       對於合數,只要將2中的P-1替換成\varphi(p)

對於ax\equiv 1(mod\,n)等價於ax+by=1,可使用擴展歐幾里得求解x

  性質

  • 若m爲原根,則恰好有\varphi (\varphi (m))個在模m下的不同原根
  • a^x \equiv a^y(mode\,m) \Leftrightarrow x \equiv y(mod\,\,ord_m(a))
  • ord_m(a) = \varphi (m)

求原根g的模板:

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;

const int maxn = 1e6+5;

LL p, primes[maxn], cnt;
bool vis[maxn];

LL fp(LL x, LL a){
    LL res = 1;
    for(x %= p; a; a >>= 1, x = x*x%p)
        if(a & 1) res = res * x % p;
    return res;
}

void get_prime(int x){    //篩出x以內的素數
    for(int i = 2; i <= x; i++){
        if(!vis[i]) prime[++cnt] = i;
        for(int j = 1; j <= cnt; j++){
            if(i * primes[j] > x) break;
            vis[i * prime[j]] = 1;
            if(i % prime[j] == 0) break;
        }
    }
}

bool check(LL x){    //檢查x是否是p的原根
    LL t = sqrt(x) + 10;
    for(int i = 1; i < prime[i] <= t; i++)
        if((p-1) % prime[i] == 0 && fp(x, (p-1)/prime[i]) % p == 1)
            return 0;
    return 1;
}

int main()
{
    scanf("%lld", &p);    //求模p的原根
    get_prime();
    
    for(int i = 1; i <= maxn; i++){
        if(check(i)){
            printf("%d\n", i);   //輸出的第一個數即爲最小原根
            return 0;
        }
    }
}

 

指標:

原根的作用就是爲了計算指標 I(指標的表示符號)。

滿足 

  • I(g^{x})=x
  • I(ab) = I(a)*I(b)
  • I(a^k)=k*I(a)

最常見的應用:解模高次方程

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章