整数的阶:设a和n是互素的正整数,使得a^x=1(mod n)成立的最小的正整数x称为a模n的阶
//求阶模板:A^x=1(mod M),调用GetJie(A,M) //输入:10^10>A,M>1 //输出:无解返回-1,有解返回最小正整数x //复杂度:O(M^(0.5)) long long gcd(long long a,long long b) { if(b==0) return a; return gcd(b,a%b); } //欧拉函数:复杂度O(n^(0.5)),返回[1,n-1]中所有和n互素的数的个数和 long long phi(long long x) { long long sum=x; for(long long i=2;i*i<=x;i++) { if(x%i==0) { sum=sum-sum/i; while(x%i==0) x/=i; } } if(x!=1) sum=sum-sum/x; return sum; } long long Mod_Mul(long long a,long long b,long long mod) { long long sum=0; while(b) { if(b&1) sum=(sum+a)%mod; b>>=1; a = (a+a)%mod; } return sum; } //a^b%mod 快速幂 long long Quk_Mul(long long a,long long b,long long mod) { long long qsum=1; while(b) { if(b&1) qsum=Mod_Mul(qsum,a,mod); b>>=1; a=Mod_Mul(a, a, mod); } return qsum; } long long GetJie(long long A,long long M) { long long d = gcd(A,M); if(d != 1) return -1; long long m=phi(M); //然后对m进行拆分 long long prm[40],prmcnt[40]; int pcnt=0; memset(prmcnt,0,sizeof(prmcnt)); long long tm = m; for(long long i=2;i*i<=tm;i++) { if(tm%i==0) { prm[pcnt]=i; while(tm%i==0) { prmcnt[pcnt]++; tm/=i; } pcnt++; } } if(tm!=1) { prm[pcnt]=tm; prmcnt[pcnt]=1; pcnt++; } for(int i=0;i<pcnt;i++) { for(int j=0;j<prmcnt[i];j++) { if( Quk_Mul(A, m/prm[i], M)==1 ) { m/=prm[i]; } } } return m; }
//再加一个打素数表的。理论上会快10倍。
//求阶模板:A^x=1(mod M),调用GetJie(A,M) //输入:10^10>A,M>1 //输出:无解返回-1,有解返回最小正整数x //复杂度:M^(0.5) long long PRIME[100100]; long long gcd(long long a,long long b) { if(b==0) return a; return gcd(b,a%b); } //欧拉函数:复杂度O(n^(0.5)),返回[1,n-1]中所有和n互素的数的个数和 long long phi(long long x) { long long sum=x; long long p = PRIME[0]; for(int i=0;p*p<=x;i++) { if(0 == x%p) { sum=sum-sum/p; while(x%p==0) x/=p; } p=PRIME[i+1]; } if(x!=1) sum=sum-sum/x; return sum; } long long Mod_Mul(long long a,long long b,long long mod) { long long sum=0; while(b) { if(b&1) sum=(sum+a)%mod; b>>=1; a = (a+a)%mod; } return sum; } //a^b%mod 快速幂 long long Quk_Mul(long long a,long long b,long long mod) { long long qsum=1; while(b) { if(b&1) qsum=Mod_Mul(qsum,a,mod);//mod不是很大的时候这一步可以去掉 b>>=1; a=Mod_Mul(a, a, mod);// } return qsum; } long long GetJie(long long A,long long M) { long long d = gcd(A,M); if(d != 1) return -1; long long m=phi(M); //然后对m进行拆分 long long prm[40],prmcnt[40]; int pcnt=0; memset(prmcnt,0,sizeof(prmcnt)); long long tm = m; long long p=PRIME[0]; for(long long i=0;p*p<=tm;i++) { if(tm%p==0) { prm[pcnt]=p; while(tm%p==0) { prmcnt[pcnt]++; tm/=p; } pcnt++; } p=PRIME[i+1]; } if(tm!=1) { prm[pcnt]=tm; prmcnt[pcnt]=1; pcnt++; } for(int i=0;i<pcnt;i++) { for(int j=0;j<prmcnt[i];j++) { if( Quk_Mul(A, m/prm[i], M)==1 ) { m/=prm[i]; } } } return m; } void getprime(long long up) { bool pmark[200100]; memset(pmark,0,sizeof(pmark)); int pcnt=0; PRIME[pcnt++]=2; for(int i=2;i<=up;i+=2) pmark[i]=1; for(int i=3;i<=up;i+=2) { if(pmark[i]==0) { PRIME[ pcnt++ ] = i; for(int j=i+i;j<=up;j+=i) { pmark[j]=1; } } } }