若n,a爲正整數,且n,a互質,(a,n) = 1,則a^φ(n) ≡ 1 (mod n)
特別的φ(1)=1函數
費馬小定理是歐拉定理的一種特殊狀況spa
以前介紹的費馬小定理是用來化簡冪取模運算的,歐拉定理一樣能夠作到:code
a^x≡a^(x%φ(m))(mod m)blog
這樣就能夠了it
以前的費馬小定理是讓指數部分模一個p-1io
而後這裏是讓指數部分模一個歐拉函數φ(m)其實一個意思class
看一道例題,HDU1395搜索
2^x mod n = 1,或者寫成 2^x ≡ 1 (mod n) 循環
求x方法
而後發現n爲偶數或者是n爲0時無解,答案一定是一個奇數
而後根據歐拉定理:
歐拉定理:a^(euler_phi(n))≡1(mod n),(a,n互質)
其中euler_phi爲歐拉函數,計算不超過n且與n互質的個數
求法是n*∏(pi-1)/pi,pi爲n的質因子
這裏能夠表示爲:m=euler_phi(n)
因此a^m%mod=1
不過m不必定是最小循環節,但m是一個循環節,則最小循環節一定是m的一個因子
於是找出全部m的因子,暴力搜索下就行了
其實這個的重點是求歐拉函數,歐拉函數也是有相似於埃式篩法的計算方法的
1 //2^x mod n = 1 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 using namespace std; 6 long long t,mod; 7 long long e[1005]; 8 long long euler_phi(long long n) 9 { 10 long long m=sqrt(n+0.5); 11 long long ans=n; 12 for(int i=2;i<=m;i++) 13 { 14 if(n%i==0) 15 { 16 ans=ans/i*(i-1); 17 while(n%i==0) n=n/i; 18 } 19 } 20 if(n>1) ans=ans/n*(n-1); 21 return ans; 22 } 23 void find(long long n) 24 { 25 e[t++]=n; 26 for(int i=2;i*i<=n;i++) 27 { 28 if(n%i==0) 29 { 30 if(i*i==n) e[t++]=i; 31 else 32 { 33 e[t++]=i; 34 e[t++]=n/i; 35 } 36 } 37 } 38 } 39 long long pows(long long a,long long b) 40 { 41 long long s=1; 42 while(b!=0) 43 { 44 if(b&1) s=(s*a)%mod; 45 a=(a*a)%mod; 46 b=b>>1; 47 } 48 return s; 49 } 50 int main() 51 { 52 long long n; 53 while(scanf("%lld",&n)==1) 54 if(n%2==0||n==1) 55 printf("2^? mod %d = 1\n",n); 56 else 57 { 58 long long m,ans; 59 m=euler_phi(n); 60 t=0; 61 find(m); 62 sort(e,e+t); 63 mod=n; 64 for(int i=0;i<t;i++) 65 { 66 if(pows(2,e[i])==1) 67 { 68 ans=e[i]; 69 break; 70 } 71 } 72 printf("2^%d mod %d = 1\n",ans,n); 73 } 74 return 0; 75 }
再回過頭來對比一下歐拉定理和費馬小定理
費馬小定理要求模數p必須是個質數,且a和p互質:a^(p-1) ≡1(mod p)
歐拉定理只要求a和m互質便可:a^φ(m)≡1(mod m)