【HDU 4992】 Primitive Roots (原根)
Description
We say that integer x, 0 < x < n, is a primitive root modulo n if and only if the minimum positive integer y which makes x y = 1 (mod n) true is φ(n) .Here φ(n) is an arithmetic function that counts the totatives of n, that is, the positive integers less than or equal to n that are relatively prime to n. Write a program which given any positive integer n( 2 <= n < 1000000) outputs all primitive roots of n in ascending order.Input
Multi test cases.
Each line of the input contains a positive integer n. Input is terminated by the end-of-file seperator.Output
For each n, outputs all primitive roots of n in ascending order in a single line, if there is no primitive root for n just print -1 in a single line.Sample Input
4 25Sample Output
3 2 3 8 12 13 17 22 23
【题意】
求n的所有原根,若没有就输出-1(n<=10^6)
【分析】
求出n的所有原根,不存在原根输出-1。
原根的定义题目已经给出,对于n的原根x,则满足x的y次幂模n等于1的最小y是n的欧拉函数值phi(n),也就是小于等于n且与n互质的个数。
官方的题解里面说暴力求出一个原根来,然后利用结论:
如果g是模m的原根,整数d>=0,则g的d次幂是模m的原根的一个充要条件是d和phi(m)互质。
d暴力枚举:
一个是如果gcd(g, m)=1,且g^d=1(mod m),则d为phi(m)的一个因子。换句话说如果g是m的原根,那么对于phi(m)的所有因子d(不包含phi(m)本身),g^d=1(mod m)是不成立的。我们可以通过枚举phi(m)的质因子以及g^phi(m)=1(mod m)是否成立来判断g是否是模m的原根。
然后有些不存在原根的数字利用另一条性质排除:
模m有原根的充要条件是m=2,4,p^n, 2p^n,p为奇质数,n任意正整数。
如果m没有满足上述条件,就直接输出-1。
代码如下:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<queue> 7 #include<cmath> 8 using namespace std; 9 #define LL long long 10 #define Maxn 1000010 11 12 int phi[Maxn],pri[Maxn],pl; 13 bool q[Maxn],qs[Maxn]; 14 15 int gcd(int a,int b) 16 { 17 if(b==0) return a; 18 return gcd(b,a%b); 19 } 20 21 void get_phi(int mx) 22 { 23 pl=0; 24 memset(q,1,sizeof(q)); 25 memset(qs,0,sizeof(qs)); 26 phi[1]=1; 27 for(int i=2;i<=mx;i++) 28 { 29 if(q[i]) pri[++pl]=i,qs[i]=i==2?0:1,phi[i]=i-1; 30 for(int j=1;j<=pl;j++) 31 { 32 if(i*pri[j]>mx) break; 33 q[i*pri[j]]=0; 34 if(i%pri[j]==0) 35 { 36 phi[i*pri[j]]=phi[i]*pri[j]; 37 if(qs[i]) qs[i*pri[j]]=1; 38 } 39 else phi[i*pri[j]]=phi[i]*(pri[j]-1); 40 if(i%pri[j]==0) break; 41 } 42 } 43 for(int i=mx/2;i>=1;i--) if(qs[i]) qs[2*i]=1; 44 qs[2]=1;qs[4]=1; 45 } 46 47 int qpow(int x,int y,int p) 48 { 49 LL ans=1,xx=x,pp=p; 50 while(y) 51 { 52 if(y&1) ans=(ans*xx)%pp; 53 xx=(xx*xx)%pp; 54 y>>=1; 55 } 56 return (int)ans; 57 } 58 59 int np[Maxn],nl; 60 void div(int x) 61 { 62 nl=0; 63 for(int i=1;pri[i]*pri[i]<=x;i++) if(x%pri[i]==0) 64 { 65 np[++nl]=pri[i]; 66 while(x%pri[i]==0) x/=pri[i]; 67 } 68 if(x>1) np[++nl]=x; 69 } 70 71 int ffind(int n) 72 { 73 div(phi[n]); 74 for(int i=2;i<=n;i++) 75 { 76 if(qpow(i,phi[n],n)!=1) continue; 77 bool ok=1; 78 for(int j=1;j<=nl;j++) 79 { 80 if(qpow(i,phi[n]/np[j],n)==1) {ok=0;break;} 81 } 82 if(!ok) continue; 83 return i; 84 } 85 return -1; 86 } 87 88 int op[Maxn]; 89 90 void output(int g,int n) 91 { 92 op[0]=0; 93 op[++op[0]]=g; 94 LL M=(LL)n,now=(LL)g,gg=(LL)g; 95 for(int i=2;i<phi[n];i++) 96 { 97 now=(now*gg)%M; 98 if(gcd(i,phi[n])==1) op[++op[0]]=(int)now; 99 } 100 } 101 102 int main() 103 { 104 get_phi(1000000); 105 int n; 106 while(scanf("%d",&n)!=EOF) 107 { 108 if(!qs[n]) {printf("-1\n");continue;} 109 int g=ffind(n); 110 output(g,n); 111 sort(op+1,op+op[0]+1); 112 for(int i=1;i<=op[0];i++) printf("%d ",op[i]); 113 printf("\n"); 114 } 115 return 0; 116 }
2016-09-06 16:39:31