【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
25

Sample 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。

 

http://blog.csdn.net/hongrock/article/details/39179291

 


 代码如下:

  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 }
[HDU 4992]

 

2016-09-06 16:39:31

posted @ 2016-09-06 16:34  konjak魔芋  阅读(613)  评论(0编辑  收藏  举报