歐拉定理:html
若正整數 a , n 互質,則 aφ(n)≡1(mod n) 其中 φ(n) 是歐拉函數(1~n) 與 n 互質的數。算法
證實以下:函數
不妨設X1,X2 ...... Xφn是1~n與n互質的數。spa
首先咱們先來考慮一些數:aX1,aX2 ...... aXφn
code
這些數有以下兩個性質:htm
(1)任意兩個數模n餘數必定不一樣:(反證)若存在aX1≡aX2(mod n),則 n |( aX1 - aX2 ),而a,n互質且(X1 - X2)< n,因此n不可能整除( aX1 - aX2 ),也就是說
blog
不存在aX1≡aX2(mod n)。概括法:對於任意的與n互質的Xi均成立。故得證。 排序
那麼由於有 φn 個這樣的數,Xi mod n(i=1~φn)因此就有 φn 個不一樣的餘數,而且都是模數天然是(0~n-1)。it
(2)對於任意的aXi(mod n)都與n互質。這不難想,由於a與n互質這是歐拉函數的條件,Xi是(1~n)與n互質的數的集合中的元素。因此若是a*Xi作爲分子,n作爲分母,那麼io
他們構成的顯然就是一個最簡分數,也就是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); } }