歐拉定理:
若正整數 a , n 互質,則 aφ(n)≡1(mod n) 其中 φ(n) 是歐拉函數(1~n) 與 n 互質的數。
證明如下:
不妨設X1,X2 ...... Xφn是1~n與n互質的數。
首先我們先來考慮一些數:aX1,aX2 ...... aXφn
這些數有如下兩個性質:
(1)任意兩個數模n余數一定不同:(反證)若存在aX1≡aX2(mod n),則 n |( aX1 - aX2 ),而a,n互質且(X1 - X2)< n,所以n不可能整除( aX1 - aX2 ),也就是說
不存在aX1≡aX2(mod n)。歸納法:對於任意的與n互質的Xi均成立。故得證。
那么因為有 φn 個這樣的數,Xi mod n(i=1~φn)所以就有 φn 個不同的余數,並且都是模數自然是(0~n-1)。
(2)對於任意的aXi(mod n)都與n互質。這不難想,因為a與n互質這是歐拉函數的條件,Xi是(1~n)與n互質的數的集合中的元素。所以如果a*Xi做為分子,n做為分母,那么
他們構成的顯然就是一個最簡分數,也就是aXi和n互質。接下來就可以用歐幾里得算法:因為:gcd(aXi,n)==1所以:gcd(aXi,n)== gcd(n,aXi%n)== 1
這樣,我們把上面兩個性質結合一下來說,aX1(mod n),aX2(mod n) ...... aXφn(mod n)構成了一個集合(性質1證明了所有元素的互異性),並且這些數是1~n與n互
質的所有數構成的集合(性質1已說明)。這樣,我們巧妙的發現了,集合{ aX1(mod n),aX2(mod n) ...... aXφn(mod n)}經過一定的排序后和集合{ X1,X2 ...... Xφn }
完全一一對應。那么:aX1(mod n)* aX2(mod n)* ...... * aXφn(mod n)= X1 * X2 * ...... * Xφn 因此:我們可以寫出以下式子:
aX1 * aX2 * ...... * aXφn ≡ X1 * X2 * ...... * Xφn (mod n),即:(aφn -1)X1 * X2 * ...... * Xφn ≡ 0 (mod n)
又因為X1 * X2 * ...... * Xφn與n互質,所以, (aφn -1)| n,那么aφn ≡ 1(mod n)。歐拉定理得證。
費馬小定理:
對於質數p,任意整數a,均滿足:ap≡a(mod p)
證明如下:
這個可以用歐拉定理來說明:首先,我們把這個式子做一個簡單變換得:ap-1 * a ≡ a(mod p) 因為a ≡ a(mod p)恆成立,所以ap-1 mod p == 1時費馬小定理才成立,又因為p
是質數,所以 φn == n-1 ,所以根據歐拉定理:若a,p互質則ap-1 mod p == 1成立。那么對於a,p不互質,因為p是質數,所以,a一定是倍數ap ≡ a ≡ 0(mod p)。綜上所述,費馬小定理
成立,其實它算是歐拉定理的一個特例。
歐拉定理的推論:
若正整數a,n互質,那么對於任意正整數b,有ab≡ab mod φ(n)(mod n)
證明如下:(類似費馬小定理的證明)
把目標式做一簡單變形:ab - b mod φ(n)* ab mod φ(n)≡ ab mod φ(n)(mod n),所以接下來只需要證明ab - b mod φ(n)≡ 1 (mod n),又因為:
( b - b mod φ(n))| φ(n),不妨設:( b - b mod φ(n))= q*φ(n)(q為自然數),則有aq*φ(n)== (aq)φ(n),因為a,n互質,那么(aq)與n也互質,
那么就轉換到了歐拉定理:(aq)φ(n)≡ 1 (mod n),成立。所以我們這個推論成立。
這個推論可以幫助我們在求冪運算的時候縮小數據范圍和計算次數。具體的說:在求乘方運算時,可以先把底數對mod取模,再把指數對b mod φ(n)取模。
特別的,如果a,mod不互質,且b>φ(n)時,ab≡ab mod φ(n)+ φ(n)(mod n)。
下面我們就用這個推論來做一道題:// http://www.nyzoj.com:5283/problem/6
題目:
給定a,n求出 S=((((aa)a)a)a⋅⋅⋅⋅)a (mod 998244353)共n個a。
輸入:
輸入僅一行. 兩個正整數a和n。
輸出:
輸出僅一行. 一個正整數S。
樣例解釋:
((22)2)2 mod 998244353 = 256
數據范圍:
a,n <= 1018
思路:
先求出指數,即an-1(快速冪求解),並將指數對mod-1(因為mod是質數,那么φ(mod)= mod-1),再用更新后的指數做為新的指數用快速冪求解即可。代碼如下:
#include<cstdio> typedef long long ll; ll a,n; const int M=998244353; ll mi(ll a,ll b,int mod) { ll re=1; a%=mod; while (b) { if (b&1) re=(re*a)%mod; a=(a*a)%mod; b>>=1; } return re; } int main() { scanf ("%lld%lld",&a,&n); ll t=mi(a,n-1,M-1); printf("%lld",mi(a,t,M)); return 0; }
課后例題://poj 3696
給定一個正整數L,L <= 2*109. 問多少個8連在一起的數是L的倍數。如果不存在就輸出0.
//這里省略輸入輸出規則,請讀者自行注意
思路:
x個8連在一起可以寫成8*(10x-1)*9,假設d=gcd(L,8)。那么題目可以表達為:L | 8*(10x-1)*9 , 接下來我們做一些簡單的式子變形:
L | 8*(10x-1)/9 ←→ L*9 | 8*(10x-1) ←→ 9L/d | (10x-1) ←→ 10x ≡ 1 (mod 9L/d)
引理:對於任意互質的正整數a,n,滿足:ax≡1(mod n)最小的整數值 X0 是φ(n)的約數。
證明如下:
(反證法)假設X0不是φ(n)的約數,則φ(n)可以表示為:qX0 + r(0 <= r < X0)。題設有:aX0≡1(mod n),那么,aqX0≡1(mod n)且正整數a,n互質,所以有歐拉定理:
aφ(n)≡1(mod n),即:aqX0 * ar≡1(mod n),繼而得出:ar≡1(mod n),此時r<X0,這與X0是最小的整數值矛盾,所以假設不成立。得證。
所以,接下來我們只需要求出φ(9L/d)並將其約數帶入10x ≡ 1 (mod 9L/d)驗證是否成立即可。求歐拉函數和快速冪,時間復雜度為:O(√(n) * log2 n)。代碼如下:
#include<cstdio> #include<algorithm> using namespace std; typedef long long ll; ll n,mod; int Case; ll gcd(ll a,ll b) { return a%b==0 ? b : gcd(b,a%b); } ll Er(ll x) { ll re=x; for (ll i=2;i*i<=x;i++) { if (x%i==0) { re=re/i*(i-1); while (x%i==0) x/=i; } } if (x>1) re=re/x*(x-1); return re; } ll mul(ll a,ll b,ll p) { ll re=0; while (b) { if (b&1) re=(re+a)%p; a=2*a%p; b>>=1; } return re; } ll ksm(ll a,ll b,ll p) { ll re=1; a%=p; while (b) { if (b&1) re=mul(re,a,p); a=mul(a,a,p); b>>=1; } return re; } int main() { while (scanf ("%lld",&n)) { if (n==0) return 0; Case++; ll d=gcd(n,8); ll phi=Er(9*n/d); mod=9*n/d; ll flag=9223372036854775806; for (ll i=1;i*i<=phi;i++) { if (phi%i==0) { if (ksm(10,i,mod)==1) flag=min(flag,i); if (ksm(10,phi/i,mod)==1) flag=min(flag,phi/i); } } flag==9223372036854775806?printf("Case %d: 0\n",Case):printf("Case %d: %lld\n",Case,flag); } }