定义: 设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; } }