51nod 1135 原根
Posted GraceSkyer
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod 1135 原根相关的知识,希望对你有一定的参考价值。
题目链接:51nod 1135 原根
设 m 是正整数,a是整数,若a模m的阶等于φ(m),则称 a 为 模m的一个原根。(其中φ(m)表示m的欧拉函数)
阶:gcd(a,m)=1,使得成立的最小的 r,称为 a 对 模m 的 阶。
φ(m):在[1,m)的区间内与m互质的数的个数。
求模素数p的原根a的方法:
因为p为素数,所以φ(p)=p-1, 这题就是要找最小的a使得 a^(p-1)%p = 1 成立(根据费马小定理,该式一定成立),
先求p-1所有不同的 质因子 p1,p2…pm,
对任何整数 a ∈[1,p-1], 检验 a 是否为 p 的原根,
检验方法:a^((p-1)/p1),a^((p-1)/p2),...a^((p-1)/pm) 中是否存在一个 模p 等于 1 ,
存在的话 a 就不是 模p 的一个原根(即p-1就不是a对模p的阶),否则a就为原根。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<vector> 5 #include<queue> 6 #define CLR(a,b) memset((a),(b),sizeof((a))) 7 using namespace std; 8 typedef long long ll; 9 const int N = 50000; 10 int prime[N];//prime[0] 存的是素数的个数 11 int ppri[N];//p-1的质因子 12 void getPrime(){ 13 CLR(prime , 0); 14 for(int i = 2;i < N; i++){ 15 if(!prime[i]) 16 prime[ ++prime[0] ] = i; 17 for(int j = 1; j <= prime[0] && prime[j] <= N / i; j++){ 18 prime[ prime[j] * i ] = 1; 19 if(i % prime[j] == 0) break; 20 } 21 } 22 } 23 ll pow_m(ll a, ll n, ll m){ 24 ll t = a % m; 25 ll r = 1; 26 while(n > 0){ 27 if(n & 1) 28 r = r * t % m; 29 t = t * t % m; 30 n >>= 1; 31 } 32 return r; 33 } 34 int divide(int n){//分解合数n的质因子 35 int cnt = 0; 36 for(int i = 1; prime[i] * prime[i] <= n; ++i){ 37 if(n % prime[i] == 0){ 38 ppri[++cnt] = prime[i]; 39 while(n % prime[i] == 0){ 40 n /= prime[i]; 41 } 42 } 43 } 44 if(n > 1) ppri[++cnt] = n; 45 return cnt; 46 } 47 int main(){ 48 int p, i, a, t, f; 49 getPrime(); 50 scanf("%d", &p); 51 int cnt = divide(p - 1);//p-1 的 质因子个数 52 for(a = 2; a <= p - 1; ++a){//原根从 2 到 p-1 枚举 53 f = 1; 54 for(i = 1; i <= cnt; ++i){ 55 t = (p - 1) / ppri[i]; 56 if( pow_m(a, t, p) == 1){ 57 //存在a^((p-1)/ppr[i]) mod p = 1, 则 a 不是质数p的原根 58 f = 0; break; 59 } 60 } 61 if(f){ 62 printf("%d\\n",a); 63 break; 64 } 65 } 66 return 0; 67 }
以上是关于51nod 1135 原根的主要内容,如果未能解决你的问题,请参考以下文章