定義: 設m>1,gcd(a,m)=1,使得
成立的最小正整數d為a對模m的階,記為δm(a)
如果δm(a)=φ(m),則稱a是模m的原根
定理:設m>1,gcd(a,m)=1,那么正整數x是同於方程
的一個根當且僅當δm(a) | x
定理:由歐拉定理得
gcd(a,n)=1
定理:模m有原根的充要條件是m=2,4,
,其中p為奇質數,n為任意正整數
定理:素數必有原根,如果一個數n有原根那么他有φ(φ(n))個模n不同余的原根
求模素數p的原根的方法:對p-1素因子分解,即p-1=
的標准分解式,若有
成立,
則a就是p的原根。(對於合數求原根,除了需要預先判斷是否存在原根之外,還需要把p-1換成φ(p))
求素數的最小原根程序
const int maxn=100000; int prime[maxn]; void Get_Prime(){ memset(prime,0,sizeof(prime)); for(int i=2;i<=maxn;i++){ if(!prime[i]) prime[++prime[0]]=i; for(int j=1;j<=prime[0]&&prime[j]<=maxn/i;j++){ prime[prime[j]*i]=1; if(i%prime[j]==0) break; } } //for(int i=1;i<=20;i++) cout<<prime[i]<<endl; } long long factor[100][2]; int fatCnt; int GetFactors(long long x){ fatCnt=0; long long tmp=x; for(int i=1;prime[i]<=tmp/prime[i];i++){ factor[fatCnt][1]=0; if(tmp%prime[i]==0){ factor[fatCnt][0]=prime[i]; while(tmp%prime[i]==0){ factor[fatCnt][1]++; tmp/=prime[i]; } fatCnt++; } } if(tmp!=1){ factor[fatCnt][0]=tmp; factor[fatCnt++][1]=1; } //for(int i=0;i<fatCnt;i++) cout<<"yinzi="<<factor[i][0]<<" mi="<<factor[i][1]<<endl; return fatCnt; } template<class T> T fast_mod(T a,T b,T Mod){ a%=mod; if(b==0) return 1; T ans=1,base=a; while(b!=0){ if(b&1)ans=(ans*base)%Mod; base=(base*base)%Mod; b>>=1; } return ans; } //判斷一個數是否有原根 bool judge(int n){ if(n==2||n==4) return true; GetFactors(n); if(fatCnt==1) return true; if(fatCnt==2&&factor[0][0]==2&&factor[0][1]==1) return true; return false; } //返回最小的原根,如果沒有則返回-1 int Solve(int P){ if(P==2) return 1; //if(!judge(P)) return false; GetFactors(P-1); for(int g=2;g<P;g++){ bool flag=true; for(int i=0;i<fatCnt;i++){ int t=(P-1)/factor[i][0]; if(fast_mod(g,t,P)==1) { flag=false;break; } } if(flag) return g; } }
