原根与指标,离散对数

原根:

  定义

设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)

最常见的应用:解模高次方程

 

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