首先是歐拉函數
定義: 歐拉函數φ(N)是小于或等于N的正整數中與N互質的數的個數(N>0)
其值為
φ(N)=N \times (1-1/P_1) \times (1-1/P_2) \times (1-1/P_3) \times ... \times (1-1/P_k)
其中P_i為N的質因數,總共有k個
因此可以利用質數篩法在線性或趨近線性的時間內完成某一區間的歐拉函數:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define maxn 10000000 | |
int euler[maxn+5]; | |
bool is_prime[maxn+5]; | |
inline void init_euler(){ | |
is_prime[1]=1;//一不是質數 | |
for(int i=1;i<=maxn;i++)euler[i]=i; | |
for(int i=2;i<=maxn;i++){ | |
if(!is_prime[i]){//是質數 | |
euler[i]--; | |
for(int j=i<<1;j<=maxn;j+=i){ | |
is_prime[j]=1; | |
euler[j]=euler[j]/i*(i-1); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
inline int Euler(int n){ | |
int ans=n; | |
for(int i=2;i*i<=n;i++){ | |
if(n%i==0){ | |
ans=ans/i*(i-1); | |
while(n%i==0)n/=i; | |
} | |
} | |
if(n>1)ans=ans/n*(n-1); | |
return ans; | |
} |
一整數A對同餘B之乘法模逆元是指滿足以下公式的整數RA^{-1}≡R \; (mod \; B)
也可以寫成AR≡1 \; (mod \; B)
根據歐拉定理: 當gcd(A,B)=1,A^{φ(B)} ≡ 1 \; mod \;B
(若B是質數,則φ(B)=B-1,競賽題目B大多為質數,不需求歐拉函數)
為了方便,我們定義 X\%Y 表示X除以Y的餘數
顯然 R=A^{φ(B)-1} \;\% \; B 是A的模B乘法模逆元,可以由次方快速冪再\ord{logn}的時間得到:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
inline long long pow_mod(int a,int b){//條件:gcd(a,b)=1 | |
long long mod=b,tmd=a,ans=1; | |
for(b=Euler(b)-1;b;b>>=1){ | |
if(b&1)ans=ans*tmd%mod; | |
tmd=tmd*tmd%mod; | |
} | |
return ans; | |
} |
計算A的模B乘法模逆元,可由擴展歐幾里得演算法得到
設exgcd擴展歐幾里得演算法的函數,它接受兩個整數A,B,輸出三個整數g,x,y。
g,x,y滿足等式A \times x+B \times y=g,且g=gcd(A,B)。
當B=0時,有x=1,\; y=0使等式成立
當B>0,在歐基里德算法的基礎上,已知gcd(A,B)=gcd(B,A\%B)
先遞迴求出x^{'},y^{'}滿足Bx^{'}+(A\%B)y^{'}=gcd(B,A\%B)=gcd(A,B)
然後可以將上面的式子化簡得Bx^{'}+(A-(A/B) \times B)y^{'}=gcd(A,B)Ay^{'}+Bx^{'}-(A/B) \times By^{'}=gcd(A,B)
這裡的除法是整除法,會自動無條件捨去。把含B的因式提取一個B,可得Ay^{'}+B(x^{'}-(A/B) \times y^{'})=gcd(A,B)
故x=y^{'},\; y=x^{'}-(A/B) \times y^{'}
若g=1,則A的模B乘法模逆元為B+x
(A \times x+B \times y)\%B=1 \longrightarrow B \times y是B的倍數 \longrightarrow A(x+B)\%B=1 \; (因為x可能小於0)
總複雜度和歐基里德算法相同,皆為\ord{logn}
擴展歐幾里得演算法函數實做:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template<typename T> | |
T exgcd(T a,T b,T &x,T &y){//a*x+b*y=(return) | |
if(b){ | |
T tmd=exgcd(b,a%b,y,x); | |
y-=a/b*x; | |
return tmd; | |
} | |
x=1,y=0; | |
return a; | |
} |
沒有留言:
張貼留言