1.原根定义:设m>1,gcd(a,m)=1,使得成立的最小的r,称为a对模m的阶。
2.定理:如果模m有原根,那么他一共有个φ(φ(m))原根。
3.定理:如果p为素数,那么素数p一定存在原根,并且模p的原根的个数为φ(p-1)个。
4.定理:假设m是正整数,a是整数,如果a模m的阶等于,则称a为模m的一个原根。
5.模m有原根的充要条件:m=2,4,P^a,2*P^a…….
求模素数P的原根的方法:对P-1素因子分解,即P-1=(P1^a1)(P2^a2)…..(Pk^ak)。,若恒有成立,那么g就是P的原根(对于合数而言,只需要把p-1换成φ(φ(p))即可)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<ctime> 6 #include<cmath> 7 #include<algorithm> 8 using namespace std; 9 #define FILE "read" 10 int p,cnt,len,pr[50010],prime[50010],isprime[50010]; 11 int gcd(int a,int b) {return !b?a:gcd(b,a%b);} 12 int fast(int a,int b,int mod) {int sum=1;for(;b;b>>=1,a=a*a%mod)if(b&1)sum*=a;return sum;} 13 inline int read() 14 { 15 int x=0,f=1; char ch=getchar(); 16 while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();} 17 while(isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();} 18 return x*f; 19 } 20 void get() 21 { 22 for(int i=2;i<=50000;i++) 23 { 24 if(!isprime[i]) prime[++cnt]=i; 25 for(int j=1;j<=cnt&&prime[j]*i<=50000;j++) 26 { 27 isprime[prime[j]*i]=1; 28 if(i%prime[j]==0) break; 29 } 30 } 31 int temp=p-1; 32 for(int i=1;i<=cnt;i++) 33 { 34 if(temp%prime[i]==0) pr[++len]=prime[i]; 35 while(temp%prime[i]==0) temp/=prime[i]; 36 } 37 if(temp>1) pr[++len]=temp; 38 } 39 bool check(int d) 40 { 41 if(gcd(p,d)!=1) return 0; 42 for(int i=1;i<=len;i++) if(fast(d,(p-1)/pr[i],p)==1) return 0; 43 return 1; 44 } 45 int main() 46 { 47 freopen(FILE".in","r",stdin); 48 freopen(FILE".out","w",stdout); 49 p=read(); get(); 50 for(int i=2;i<p;i++) if(check(i)) {printf("%d ",i); break;} 51 return 0; 52 }