原根:
定义
设m是正整数,a是整数,若a mod m 的阶等于,则称a为模m的一个原根(表示m的欧拉函数)
当且仅当指数为P - 1的时候,成立,则质数P的原根即为g
求解方法:1.将p-1进行质因数分解
2.枚举i,并判断对于每个i是否都有,第一个符合i的即是P 的最小原根
对于合数,只要将2中的P-1替换成
对于等价于,可使用扩展欧几里得求解x
性质
- 若m为原根,则恰好有个在模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;
}
}
}
指标:
原根的作用就是为了计算指标 (指标的表示符号)。
满足
最常见的应用:解模高次方程