眾所周知,tzc 不會數論(((
於是就來補題了(
同余與剩余系
同余與剩余系的概念
……感覺沒啥必要寫吧,但想想還是寫了。
對於某個數 \(m\),若存在兩數 \(a,b\) 滿足 \(a\bmod m=b\bmod m\),我們就稱 \(a,b\) 模 \(m\) 同余,記作 \(a\equiv b\pmod{m}\)
顯然同余有以下性質:
- 若 \(a\equiv b\pmod{m}\),\(m\mid(a-b)\)
- 若 \(a_1\equiv b_1\pmod{m},a_2\equiv b_2\pmod{m}\),則 \(a_1\pm a_2\equiv b_1\pm b_2\pmod{m}\)
- 若 \(a\equiv b\pmod{m}\),則 \(ad\equiv bd\pmod{md}\)
- 若 \(a\equiv b\pmod{m}\),則 \(\dfrac{a}{d}\equiv\dfrac{b}{d}\pmod{\dfrac{m}{\gcd(m,d)}}\)
由於這幾條性質都比較顯然就不放證明了。
對於某一集合 \(S\),記集合 \(T_m=\{x|x=y\bmod m,y\in S\}\) 為 \(S\) 在模 \(m\) 下的剩余系。若 \(T_m\) 包含 \(0,1,2,\dots,m-1\) 中的所有數,那么就稱其為模 \(m\) 意義下的完全剩余系。
斐蜀定理
咋感覺大家數論都是由二元不定方程引入的啊(
斐蜀定理講的是這樣一件事情:關於 \(x,y\) 的二元一次不定方程 \(ax+by=c\) 有解的充分必要條件是 \(c\) 是 \(\gcd(a,b)\) 的倍數。
證明:必要性:考慮反證法,假設 \(c\) 不是 \(\gcd(a,b)\) 的倍數,\(x_0,y_0\) 為滿足 \(ax+by=c\) 的 \(x,y\)。設 \(d=\gcd(a,b),a'=\dfrac{a}{d},b'=\dfrac{b}{d}\),那么 \(ax_0+by_0=a'dx_0+b'dy_0=d(a'x_0+b'y_0)\) 也應為 \(d\) 的倍數,矛盾。
充分性:這里只講一小部分。對於 \(c\) 是 \(\gcd(a,b)\) 的倍數,我們只需找出 \(ax+by=\gcd(a,b)\) 的 \(x,y\),再將其乘上 \(\dfrac{c}{\gcd(a,b)}\) 即可。至於 \(ax+by=\gcd(a,b)\) 的解怎樣求,將會在下面擴展歐幾里得的部分着重講解。
擴展歐幾里得(exgcd)
擴展歐幾里得算法可用來解不定方程 \(ax+by=\gcd(a,b)\)
回顧求 \(a,b\) 的 gcd 的方法,若 \(b=0\),那么直接返回 \(a\),否則遞歸求解 \(\gcd(b,a\bmod b)\)。
擴展歐幾里得也是采用類似的做法,若 \(b=0\),那么 \(\gcd(a,b)=a\),原二元一次不定方程變為 \(ax=a\),\(x=1,y=0\) 即可。
若 \(b\neq 0\),遞歸求解不定方程 \(bx+(a\bmod b)y=\gcd(b,a\bmod b)\) 的解 \(x_0,y_0\)。根據求 \(\gcd\) 的過程可知 \(\gcd(a,b)=\gcd(b,a\bmod b)\),故 \(bx_0+(a\bmod b)y_0=\gcd(a,b)\),而 \(a\bmod b=a-\lfloor\dfrac{a}{b}\rfloor\times b\),故 \(bx_0+(a-\lfloor\dfrac{a}{b}\rfloor\times b)y_0=\gcd(a,b)\),整理一下可得 \(ay_0+b(x_0-\lfloor\dfrac{a}{b}\rfloor\times y_0)=\gcd(a,b)\),故方程 \(ax+by=\gcd(a,b)\) 的一組解為 \(x=y_0,y=x_0-\lfloor\dfrac{a}{b}\rfloor\times y_0\)。如此不斷遞歸下去就可以得到原不定方程的解了。類似於數學中的歸納法。
上述過程同時也證明了斐蜀定理的充分性。
時間復雜度同輾轉相除法,為 \(\mathcal O(\log(\max(a,b)))\)。
void exgcd(int a,int b,int &x,int &y){
if(!y){x=1;y=0;return;}
exgcd(b,a%b,x,y);int tmp=x;x=y;y=tmp-(a/b)*y;
}
逆元
回顧上面同余的各種性質,不難發現,\(a\) 與 \(b\) 加、減、乘的結果在模意義下都可以直接得出。
那除法呢?我們不妨先看一個引例:\(a\equiv 3\pmod{5}\),並且 \(a\) 是 \(2\) 的倍數,求 \(\dfrac{a}{2}\) 模 \(5\) 余幾。
顯然 \(\dfrac{a}{2}\) 模 \(5\) 余 \(4\),因為 \(0,1,2,3,4\) 中只有 \(4\) 的 \(2\) 倍模 \(5\) 余 \(3\)。
於是我們就有了逆元的定義,定義 \(a\) 模 \(m\) 的逆元 \(a^{-1}\) 為滿足 \(aa^{-1}\equiv 1\pmod{m}\) 的 \(a^{-1}\),且 \(a^{-1}\in [0,m)\)
這樣 \(\dfrac{x}{a}\equiv xa^{-1}\pmod{m}\) 因為 \(xaa^{-1}\equiv x\pmod{m}\)
顯然 \(a\) 在模 \(m\) 下的逆元唯一。否則假設 \(\exist x,y\in[0,m)\) 滿足 \(ax\equiv 1\pmod{m},ay\equiv 1\pmod{m}\),那么 \(x\equiv x(ay)=xay=(xa)y\equiv y\pmod{m}\),即 \(x\equiv y\pmod{m}\),而 \(x,y\in[0,m)\),矛盾!
那么是否所有數都有逆元呢?非也。還是看一個例子:\(a\equiv 4\pmod{6}\),並且 \(a\) 是 \(2\) 的倍數,求 \(\dfrac{a}{2}\) 模 \(6\) 余幾。
這時候我們就很糾結了,因為 \(2,5\) 的兩倍都模 \(6\) 余 \(4\)。故我們無法知道 \(\dfrac{a}{2}\) 模 \(6\) 究竟余幾。
這個故事就告訴我們:\(2\) 在模 \(6\) 意義下沒有逆元。
事實上對於所有 \((a,m)>1\) 的 \(a\) 在模 \(m\) 意義下都沒有逆元。否則假設 \(ab\equiv 1\pmod{m}\),設 \(d=\gcd(a,m),a=da',m=dm',ab=km+1\),那么 \(ab=da'b=km+1=kdm'+1\),即 \(1=da'b-kdm'=d(a'b-km')\),而 \(d>1\),矛盾!
求逆元一般有三種方法:
- 費馬小定理,對於質數 \(p\),根據費馬小定理(這個后面會提到)有 \(a^{p-1}\equiv 1\pmod{p}\),故 \(aa^{p-2}\equiv 1\pmod{p}\),即 \(a^{-1}\equiv a^{p-2}\pmod{p}\),這種方法只適用於 \(p\) 是質數的情況。
- exgcd,設 \(aa^{-1}=km+1\),那么 \(aa^{-1}-km=1\),相當於解二元一次不定方程 \(ax+my=1\),由於 \((a,m)=1\),故上面的方程等價於 \(ax+my=\gcd(a,m)\)。這個 exgcd 顯然可以解決。最后提取 \(x\) 的值即可。注意,exgcd 不是基於剩余系的,故最后求出的 \(x\) 可能是負數,需通過取模操作將其處理到 \([0,m)\) 之內。
- 線性求逆元。設 \(inv_i\) 為 \(i\) 在模 \(m\) 意義下的逆元,我們假設已經知道了 \(inv_1,inv_2,\dots,inv_{i-1}\) 的值,考慮怎樣遞推求出 \(inv_i\)。設 \(m=ki+r(r<i)\),於是 \(r\equiv -ki\pmod{m}\)。兩邊同時乘上 \(i^{-1}r^{-1}\) 可得 \(i^{-1}\equiv -kr^{-1}\pmod{m}\),而由於 \(r<i\),故 \(r^{-1}\) 我們已經事先求得了,可通過此式 \(\mathcal O(1)\) 遞推得出 \(i^{-1}\)。
中國剩余定理(CRT)
大概就是要求最小的滿足
的非負整數 \(x\),其中 \(m_1,m_2,\dots,m_n\) 兩兩互質。
要是早學 2 周就好了,WC2021 就能多個 20pts 了,就能 dd ymx 了(做白日夢 ing)
引理:在 \([0,m_1m_2\dots m_n)\) 中有且僅有一個滿足條件的 \(x\)。
證明:假設 \(\exist x_1,x_2\in[0,m_1m_2\dots m_n)\) 代入同余方程組均使方程組成立,根據同余的性質有 \(m_1\mid(x_1-x_2),m_2\mid(x_1-x_2),\dots,m_n\mid(x_1-x_2)\),即 \(\operatorname{lcm}(m_1,m_2,\dots,m_n)\mid(x_1-x_2)\),而 \(m_1,m_2,\dots,m_n\) 兩兩互質,故 \(\operatorname{lcm}(m_1,m_2,\dots,m_n)=m_1m_2\dots m_n\),於是有 \(m_1m_2\dots m_n\mid(x_1-x_2)\),而 \(x_1,x_2\in[0,m_1m_2\dots m_n)\),矛盾。而設 \(\{S=(b_1,b_2,\dots,b_n)|b_i=x\bmod m_i,x\in[0,m_1m_2\dots m_n)\}\),根據之前的證明過程可知不存在 \(x_1,x_2\in [0,m_1m_2\dots m_n)\) 滿足 \((x_1\bmod m_1,x_1\bmod m_2,\dots,x_1\bmod m_n)=(x_2\bmod m_1,x_2\bmod m_2,\dots,x_2\bmod m_n)\),故 \(|S|=m_1m_2\dots m_n\),而滿足 \(b_i<m_i\) 的 \(n\) 元組總共只有 \(m_1m_2\dots m_n\) 個,故 \(S\) 中包含所有滿足 \(b_i<m_i\) 的 \(n\) 元組 \((b_1,b_2,\dots,b_n)\),故一定存在 \(x\in[0,m_1m_2\dots m_n)\) 能使同余方程組成立。
(以上全是我在瞎扯,不知道也沒關系)
因此我們只需找出這個滿足條件的 \(x\) 即可。
考慮設 \(P=\prod\limits_{i=1}^nm_i,x_i=\dfrac{P}{m_i}\),\(t_i\) 為滿足 \(x_it_i\equiv 1\pmod{m_i}\) 的 \(t_i\),再記 \(X=\sum\limits_{i=1}^na_ix_it_i\),那么 \(X\) 就是滿足同余方程組的解了。如果題目要求最小解那就輸出 \(X\bmod{m_1m_2\dots m_n}\) 即可。
為什么?考慮其中某一項 \(x\equiv a_i\pmod{m_i}\),對於 \(X\) 中的某一項 \(a_jx_jt_j(j\neq i)\),由於 \(x_j=\dfrac{P}{m_j}=\prod\limits_{k\neq j}m_k\) 為 \(m_i\) 的倍數,故 \(a_jx_jt_j\equiv 0\pmod{m_i}\),也就是說 \(X\equiv a_ix_it_i\pmod{m_i}\),而 \(x_it_i\equiv 1\pmod{m_i}\),故 \(X\equiv a_i\pmod{m_i}\),滿足條件。
至於怎樣求這個 \(t_i\),由於 \(m_1,m_2,\dots,m_n\) 兩兩互質,\(x_i\) 與 \(t_i\) 也是互質的,故 \(t_i\) 實質上就是 \(x_i^{-1}\pmod{m_i}\)。直接 exgcd 求逆元就行了。
模板題代碼(注:兩個 long long
相乘會爆,故需手寫龜速乘):
const int MAXN=10;
int n;
ll ans=0,m[MAXN+2],a[MAXN+2],mul=1;
void exgcd(ll x,ll y,ll &a,ll &b){
if(!y){a=1;b=0;return;}
exgcd(y,x%y,a,b);ll tmp=a;a=b;b=tmp-x/y*b;
}
ll inv(ll a,ll mod){
ll x,y;exgcd(a,mod,x,y);
return (x+mod)%mod;
}
ll prod(ll a,ll b,ll mod){
ll ret=0;
for(;b;b>>=1,(a+=a)%=mod) if(b&1) (ret+=a)%=mod;
return ret;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){scanf("%lld%lld",&m[i],&a[i]);mul*=m[i];}
for(int i=1;i<=n;i++){
ll iv=inv(mul/m[i],m[i]);//exgcd 求 x[i] 的逆元 t[i]
ans=(ans+prod(prod(a[i],mul/m[i],mul),iv,mul))%mul;//龜速乘
} printf("%lld\n",ans);
return 0;
}
擴展中國剩余定理(exCRT)
還是求滿足上式的最小整數 \(x\),只不過不再保證 \(m_1,m_2,\dots,m_n\) 兩兩互質。
考慮怎樣將
兩式合並為形如 \(x\equiv a\pmod{\operatorname{lcm}(m_1,m_2)}\) 的形式。
顯然如果能解決兩式合並的問題,那么本題就解決了。
考慮設 \(x=k_1m_1+a_1=k_2m_2+a_2\)
移個項可得 \(k_1m_1-k_2m_2=a_2-a_1\)
我們發現現在的條件是已知 \(m_1,m_2,a_2-a_1\),要求符合條件的 \(k_1,k_2\)。
這不就喜聞樂見的 exgcd 嗎?
根據斐蜀定理若 \(\gcd(m_1,m_2)\nmid (a_2-a_1)\),那么方程 \(k_1m_1-k_2m_2=a_2-a_1\),整個同余方程組就無解了。
否則假設 \(x,y\) 滿足 \(xm_1+ym_2=\gcd(m_1,m_2)\),那么 \(k_1=\dfrac{x(a_2-a_1)}{\gcd(m_1,m_2)},k_2=-\dfrac{y(a_2-a_1)}{\gcd(m_1,m_2)}\) 符合條件,最后通過 \(x=k_1m_1+a_1\) 就可以合並兩個方程組了。
int n;ll ans=0,lcm=1;
void exgcd(ll x,ll y,ll &d,ll &a,ll &b){
if(!y){d=x;a=1;b=0;return;}
exgcd(y,x%y,d,a,b);ll tmp=a;a=b;b=tmp-x/y*b;
}
ll prod(ll a,ll b,ll mod){
a=(a%mod+mod)%mod;b=(b%mod+mod)%mod;
ll ret=0;
for(;b;b>>=1,(a+=a)%=mod) if(b&1) (ret+=a)%=mod;
return ret;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
ll m,a;scanf("%lld%lld",&m,&a);
ll x,y,gcd;exgcd(lcm,m,gcd,x,y);//找滿足 xm[1]+ym[2]=gcd(m[1],m[2]) 的 x,y
if(abs(a-ans)%gcd) assert(0);//如果 a[2]-a[1] 不是 gcd(m[1],m[2]) 的倍數那就無解
ll new_m=m/gcd*lcm;x=prod(x,(a-ans)/gcd,new_m);//擴大 (a[2]-a[1])/gcd(m[1],m[2]) 倍
ans=(ans+prod(x,lcm,new_m))%new_m;//x=k[1]m[1]+a[1]
lcm=new_m;
} printf("%lld\n",ans);
return 0;
}
大步小步算法(BSGS)
北上廣深(大霧)
大步小步算法可以用來解形如 \(a^x\equiv c\pmod{m}\) 的方程,其中 \(a\) 與 \(m\) 互質。
考慮根號分治,設一個閾值 \(T\),假設 \(x=pT-q\),其中 \(p\geq 1,q\in [0,T)\)
那么 \(a^x=a^{pT-q}=(a^T)^p·a^{-q}\equiv c\pmod{m}\)。
兩邊同時乘 \(a^q\) 可得 \((a^T)^p\equiv ca^q\pmod{m}\)
我們考慮這樣一個算法:預處理時枚舉 \(q\in [0,T)\) 並將 \(ca^q\) 壓入哈希表中,再枚舉 \(p\in[1,\dfrac{m}{T}]\) 並在哈希表中查詢 \((a^T)^p\)
根據歐拉定理(這個在后面會講)循環節的長度不會超過 \(\varphi(m)\),故枚舉到 \(\dfrac{m}{T}\) 是沒問題的。
時間復雜度 \(\sqrt{m}\),如果哈希表使用 std::map
會多個 log
const int MOD=19260817;
const int SQRT=1<<16;
int hd[MOD],nxt[SQRT+5],v[SQRT+5],id[SQRT+5],num=0;
void insert(int x,int t){
v[++num]=x;id[num]=t;nxt[num]=hd[x%MOD];hd[x%MOD]=num;
}
int query(int val){
for(int i=hd[val%MOD];i;i=nxt[i]) if(v[i]==val) return id[i];
return -1;
}
int p,b,n;
int main(){
scanf("%d%d%d",&p,&b,&n);int pw=1,pw2=1;
for(int i=0;i<SQRT;i++){insert(n,i);n=1ll*n*b%p;pw=1ll*pw*b%p;}//將 ca^q 壓入哈希表
for(int i=1;i<=SQRT;i++){
pw2=1ll*pw2*pw%p;
if(~query(pw2)) return printf("%d\n",i*SQRT-query(pw2)),0;//如果存在就直接輸出
} printf("no solution\n");//無解
return 0;
}
擴展大步小步算法(exBSGS)
還是解方程 \(a^x\equiv c\pmod{m}\),只不過不保證 \(a\) 與 \(m\) 互質。
考慮分兩種情況:
-
如果 \(\gcd(a,m)=1\) 那直接 BSGS 就行了。
-
如果 \(\gcd(a,m)>1\)
設 \(d=\gcd(a,m),a=a'd,m=m'd\),我們提一個 \(a\) 出來,變成 \(a^{x-1}a'd\equiv c\pmod{m'd}\)
顯然 \(c\) 必須是 \(d\) 的倍數,否則就無解了。
此時,根據同余第四條性質,我們可將同余方程左右兩邊以及模數都除以 \(d\),即 \(a^{x-1}a'\equiv\dfrac{c}{d}\pmod{m'}\)
由於 \(d=\gcd(a,m)\),一定有 \(\gcd(a',m')=1\),故 \(a'\) 在模 \(m'\) 意義下的逆元一定存在。兩邊同乘 \(a'^{-1}\) 可得 \(a^{x-1}\equiv\dfrac{c}{d}·a'^{-1}\pmod{m'}\)
發現又變成了 \(a^x\equiv c'\pmod{m'}\) 的形式。
如果 \(a,m'\) 互質那直接上個 BSGS 就完事了。
如果 \(a,m'\) 不互質那就繼續遞歸下去。不難發現每次遞歸 \(m\) 至少減半,故遞歸層數最多 \(\log m\)。
注意在轉化過程中可能出現 \(a=c\) 的情況,這時要及時停下來。
const int MOD=19260817;
const int SQRT=1<<16;
const int INF=-1e9;
int gcd(int x,int y){return (!y)?x:gcd(y,x%y);}
void exgcd(int x,int y,int &a,int &b){
if(!y){a=1;b=0;return;}
exgcd(y,x%y,a,b);int tmp=a;a=b;b=tmp-x/y*b;
}
int inv(int a,int mod){
int x,y;exgcd(a,mod,x,y);
return (x+mod)%mod;
}
struct hashtable{
int v[SQRT+5],id[SQRT+5],nxt[SQRT+5],hd[MOD],num;
void init(){for(int i=1;i<=num;i++) hd[v[i]%MOD]=0;num=0;}
void insert(int x,int t){
v[++num]=x;id[num]=t;nxt[num]=hd[x%MOD];hd[x%MOD]=num;
}
int query(int val){
for(int i=hd[val%MOD];i;i=nxt[i]) if(v[i]==val) return id[i];
return -1;
}
} ht;
int BSGS(int a,int c,int p){
ht.init();int mul=1,pw=1;
for(int i=0;i<SQRT;i++){
ht.insert(c,i);
c=1ll*c*a%p;mul=1ll*mul*a%p;
}
for(int i=1;i<=SQRT;i++){
pw=1ll*pw*mul%p;
if(~ht.query(pw)) return i*SQRT-ht.query(pw);
} return INF;
}
int solve(int a,int c,int p){
if(a==c) return 1;//特判 a=c
int d=gcd(a,p);
if(d==1) return BSGS(a,c,p);//a,p 互質就直接 BSGS
if(c%d) return INF;//如果 c 不是 gcd(a,m) 的倍數那就無解了
return solve(a%(p/d),1ll*(c/d)*inv(a/d,p/d)%(p/d),p/d)+1;//遞歸求解
}
int main(){
int a,p,b;
while(~scanf("%d%d%d",&a,&p,&b)){
if(!a||!p||!b) break;
int ans=solve(a,b,p);
if(ans==INF) printf("No Solution\n");
else printf("%d\n",ans);
}
return 0;
}
盧卡斯定理(Lucas)
我們知道,當模數 \(p\) 為質數且比較大的時候,諸如 \(998244353\),那可以通過預處理階乘逆元 \(\mathcal O(1)\) 計算組合數。
那如果 \(p\) 比較小呢?那就不能用這個算法了。因為對於 \(i\geq p\),\(i!\equiv 0\pmod{p}\),不存在逆元。
這時候就要用到 Lucas 定理了。Lucas 定理說的是這樣一件事情:對於質數 \(p\),\(\dbinom{n}{m}\equiv\dbinom{n\bmod p}{m\bmod p}\dbinom{\lfloor\frac{n}{p}\rfloor}{\lfloor\dfrac{m}{p}\rfloor}\pmod{p}\)。
簡單證明一下吧:
考慮二項式定理 \((1+x)^p=\sum\limits_{i=0}^p\dbinom{p}{i}x^i\)。
而對於 \(1\leq i\lt p\),\(\dbinom{p}{i}=\dfrac{p!}{i!(p-i)!}\equiv 0\pmod{p}\),因為 \(i!\) 和 \((p-i)!\) 均不含因子 \(p\),無法抵消。
故 \((1+x)^p\equiv 1+x^p\pmod{p}\)
接下來考慮怎樣計算 \(\dbinom{n}{m}\),顯然 \(\dbinom{n}{m}=[x^m](1+x)^n\)
將 \(n,m\) 均看作一個 \(p\) 進制數,即 \(n=\sum\limits_{i=0}^ka_ip^i,m=\sum\limits_{j=0}^kb_ip^i\),其中 \(a_i,b_i\in [0,p)\)
那么 \((1+x)^n=\prod\limits_{i=0}^k(1+x)^{a_ip^i}\)
根據 \((1+x)^p\equiv 1+x^p\pmod{p}\) 可得 \((1+x)^{a_ip^i}=(1+x^{p^i})^{a_i}\)
故 \((1+x)^n=\prod\limits_{i=0}^k(1+x^{p^i})^{a_i}\)
而根據進制的性質,不同位之間的結果不會影響。
即 \(\dbinom{n}{m}=[x^m](1+x)^n=\prod\limits_{i=0}^k[x^{b_ip^i}](1+x^{p^i})^{a_i}=\prod\limits_{i=0}^k[x^{b_i}](1+x)^{a_i}=\prod\limits_{i=0}^k\dbinom{a_i}{b_i}\)
證畢。
知道了盧卡斯定理后就可以把 \(n,m\) 當作一個 \(p\) 進制數一位一位拆開並計算 \(\dbinom{a_i}{b_i}\),由於 \(a_i,b_i<p\),可用預處理階乘逆元的方式計算 \(\dbinom{a_i}{b_i}\)。最后把結果乘起來就 ok 了。
擴展盧卡斯定理(exLucas)
真就啥都能擴展啊……
事實上 exLucas 和 Lucas 定理沒有一點關系。
Lucas 定理可以計算 \(\dbinom{n}{m}\bmod{p}\),其中 \(p\) 是質數。如果 \(p\) 不是質數怎么辦呢?就要用到 exLucas 了。
我們假設 \(p=p_1^{k_1}·p_2^{k_2}\dots p_x^{k_x}\),考慮計算其中每一項 \(\dbinom{n}{m}\bmod{p_i^{k_i}}\),然后 CRT 合並。
怎樣計算 \(\dbinom{n}{m}\bmod p^k\),還是考慮將組合數拆開,寫成 \(\dfrac{n!}{m!(n-m)!}\) 的形式。
回憶一下為什么這東西不能直接預處理階乘逆元求,因為可能存在 \(i!\bmod p^k=0\) 的情況導致壓根兒不存在逆元。
那如果我們把 \(n!\) 中的 \(p\) 因子都除掉呢?
假設 \(n!\) 中有 \(x\) 個 \(p\) 因子,\(m!\) 中有 \(y\) 個 \(p\) 因子,\((n-m)!\) 中有 \(z\) 個 \(p\) 因子。
那么 \(\dfrac{n!}{m!(n-m)!}=\dfrac{\frac{n!}{p^x}}{\frac{m!}{p^y}·\frac{(n-m)!}{p^z}}\times p^{x-y-z}\)
顯然 \(\dfrac{m!}{p^y},\dfrac{(n-m)!}{p^z}\) 均不含 \(p\) 因子,故它們都存在模 \(p^k\) 意義下的逆元。
因此如果我們知道 \(\dfrac{n!}{p^x},\dfrac{m!}{p^y},\dfrac{(n-m)!}{p^z},x,y,z\) 的值,就可以通過 exgcd 計算逆元+快速冪求出 \(\dfrac{n!}{m!(n-m)!}\bmod p^k\)。問題也就迎刃而解了。於是現在問題變為:
- 如何計算 \(\dfrac{n!}{p^x},\dfrac{m!}{p^y},\dfrac{(n-m)!}{p^z}\bmod p^k\) 的值
- 如何計算 \(x,y,z\) 的值。
先來解決第一個問題,我們將 \(1\sim n\) 中的數分成兩部分,\(1·2·3·4\dots n=(1p·2p·3p\dots(\lfloor\dfrac{n}{p}\rfloor\times p))\times(1·2·3·4\dots(p-1)·(p+1)·(p+2)\dots·(2p-1)·(2p+1)·\dots)\) 即左邊都是 \(p\) 的倍數,右邊都不是 \(p\) 的倍數。
先考慮右邊,顯然右邊所有數的乘積都會被計入 \(\dfrac{n!}{p^x}\),即 \((1·2·3·4\dots(p-1)·(p+1)·(p+2)\dots·(2p-1)·(2p+1)·\dots)\bmod p^k\)。不難發現這東西具有周期性,於是考慮將右邊這玩意兒拆成若干個整段+最后零頭部分來計算,整段的乘積顯然可以掃一遍 \(i\in [1,p^k]\) 統計所有不是 \(p\) 的倍數的 \(i\) 的乘積。共有 \(\lfloor\dfrac{n}{p^k}\rfloor\) 個整段,快速冪一下即可,最后零頭部分單獨統計。這樣就可求出 \((1·2·3·4\dots(p-1)·(p+1)·(p+2)\dots·(2p-1)·(2p+1)·\dots)\bmod p^k\) 了。
接下來考慮左邊部分,由於它們都是 \(p\) 的倍數,故計入答案時都要除以 \(p\),也就變成求 \(1·2·3\dots\lfloor\dfrac{n}{p}\rfloor\) 除去所有 \(p\) 的因子之后的乘積,這個顯然可以遞歸求出。將兩部分一合並就是答案。
接下來解決第二個問題,知道第一個問題之后第二個問題就變得異常簡單了,還是考慮將 \(1\sim n\) 的數分為兩部分,顯然右邊部分的數是不會對 \(x\) 產生貢獻的,左邊 \(\lfloor\dfrac{n}{p}\rfloor\) 個數都會對 \(x\) 產生 \(1\) 的貢獻,將左邊所有數都除以 \(p\) 並遞歸 \((\lfloor\dfrac{n}{p}\rfloor)!\) 即可。於是我們有遞推式 \(g(n)=\lfloor\dfrac{n}{p}\rfloor+g(\lfloor\dfrac{n}{p}\rfloor)\),遞歸算一算就好了。
ll n,m;int p;
void exgcd(int x,int y,int &a,int &b){
if(!y){a=1;b=0;return;}
exgcd(y,x%y,a,b);int tmp=a;a=b;b=tmp-(x/y)*b;
}
int inv(int a,int mod){
int x,y;exgcd(a,mod,x,y);
return (x+mod)%mod;
}
int qpow(int x,ll e,int mod){
int ret=1;
for(;e;e>>=1,x=1ll*x*x%mod) if(e&1) ret=1ll*ret*x%mod;
return ret;
}
int calc_f(ll n,int p,int pk){//計算 n!/p^x
if(!n) return 1;int mul1=1,mul2=1;
for(int i=1;i<=pk;i++) if(i%p) mul1=1ll*mul1*i%pk;//整段部分的乘積
mul1=qpow(mul1,n/pk,pk);
for(ll i=n/pk*pk+1;i<=n;i++) if(i%p) mul2=1ll*mul2*(i%pk)%pk;//零頭部分
return 1ll*calc_f(n/p,p,pk)*mul1%pk*mul2%pk;//遞歸計算左邊部分
}
ll calc_g(ll n,int p){if(n<p) return 0;return calc_g(n/p,p)+(n/p);}
int main(){
scanf("%lld%lld%d",&n,&m,&p);
vector<pii> fac;int tmp=p;
for(int i=2;i*i<=p;i++) if(tmp%i==0){
int mul=1;
while(tmp%i==0) tmp/=i,mul*=i;
fac.pb(mp(i,mul));
} if(tmp>1) fac.pb(mp(tmp,tmp));//預處理質因子
int ans=0;
for(int i=0;i<fac.size();i++){
int x=fac[i].fi,y=fac[i].se;
int f1=calc_f(n,x,y),f2=calc_f(m,x,y),f3=calc_f(n-m,x,y);
int if2=inv(f2,y),if3=inv(f3,y);
ll ex=calc_g(n,x)-calc_g(m,x)-calc_g(n-m,x);
int rem=1ll*f1*if2%y*if3%y*qpow(x,ex,y)%y;//C(n,m) mod p^k
int iv=inv(p/y,y);//CRT 合並
ans=(ans+1ll*(p/y)*iv%p*rem%p)%p;
} printf("%d\n",ans);
return 0;
}
二次剩余
二次剩余的定義:對於正整數 \(p\),若正整數 \(x,n\in [0,p)\) 且 \(x^2\equiv n\pmod{p}\),則稱 \(x\) 為 \(n\) 在模 \(p\) 意義下的二次剩余。(注:在 OI 中我們一般只探討奇質數 \(p\) 的二次剩余問題,下文中若無特殊說明,默認 \(p\) 為奇質數)。
若存在整數 \(x\) 使得 \(x^2\equiv n\pmod{p}\) 那么我們就稱 \(n\) 為模 \(p\) 意義下的二次剩余,否則稱 \(n\) 為模 \(p\) 意義下的二次非剩余。
歐拉判別法
對於給定的正整數 \(n\),可用歐拉判別法判斷關於 \(x\) 的同余方程 \(x^2\equiv n\pmod{p}\) 是否有解。
結論:\(n^{\frac{p-1}{2}}\bmod p=\begin{cases}1\to\text{有解}\\p-1\to\text{無解}\end{cases}\)
證明:
- 顯然對於 \(p\nmid n\),\(n^{\frac{p-1}{2}}\equiv \pm 1\pmod{p}\),因為 \((n^{\frac{p-1}{2}})^2=n^{p-1}\equiv 1\pmod{p}\),而 \([1,p-1]\) 中只有 \(1\) 和 \(p-1\) 的平方模 \(p\) 余 \(1\)。
- 若 \(n\) 為模 \(p\) 意義下的二次剩余,記 \(c\) 為滿足 \(x^2\equiv n\pmod{p}\) 的 \(x\),那么根據費馬小定理 \(n^{\frac{p-1}{2}}\equiv(c^2)^{\frac{p-1}{2}}=c^{p-1}\equiv 1\pmod{p}\)。
- 若 \(n\) 為模 \(p\) 意義下的二次非剩余,由於 \(p\nmid n\) 且 \(p\) 為奇質數,故 \(\forall x\in[1,p-1],\exist y\in [1,p-1]\) 使得 \(xy\equiv n\pmod{p}\),並且這樣的 \(y\) 也是唯一的。而 \(n\) 為模 \(p\) 意義下的二次非剩余,故不存在 \(x,y\) 滿足 \(xy\equiv n\pmod{p}\) 且 \(x=y\),故可將 \([1,p-1]\) 的中的數兩兩配對使得每一對中兩數之積模 \(p\) 為 \(n\)。計算這 \(\dfrac{p-1}{2}\) 對數的乘積可得 \(n^{\frac{p-1}{2}}\equiv (p-1)!\pmod{p}\)。那么 \((p-1)!\bmod p\) 是個什么東西呢?考慮計算 \(1\sim p-1\) 乘積的時候先單獨將 \(1,p-1\) 拎出來,顯然 \(\forall i\in[2,p-2],i^2\bmod p\neq 1\)。仿照剛才的分析過程可知 \(\forall x\in [2,p-2],\exist y\in [2,p-2]\) 滿足 \(xy\equiv 1\pmod{p}\) 且 \(x\neq y\),故 \((p-1)!\bmod p=1·(p-1)·1^{\frac{p-3}{2}}=p-1\),得證。(上述證明過程同時也證明了對於質數 \(p\) 都有 \((p-1)!\equiv p-1\pmod{p}\),這個定理有個專門的名字,叫什么威爾遜定理,不過名字啥的不重要啦)
還有一個小結論,那就是 \([1,p-1]\) 內二次剩余的的個數恰好為 \(\frac{p-1}{2}\),因為對於 \(x,y\in [1,p-1]\),\(x^2\equiv y^2\pmod{p}\) 等價於 \((x+y)(x-y)\equiv 0\pmod{p}\),而顯然 \((x-y)\bmod p\neq 0\),故 \((x+y)\bmod p=0\),故可將 \(1\sim p-1\) 中的數分成 \(\frac{p-1}{2}\) 組使得每組中的兩數都滿足 \(x^2\equiv y^2\pmod{p}\) 並且不同組之間的數的平方模 \(p\) 不同余,得證。
求二次剩余的算法
歐拉判別法只能用來判定一個數是否存在二次剩余,那怎樣求二次剩余呢?
首先有一個非常暴力的做法:由於 \(p\) 為奇質數,\(p\) 一定存在原根(這個后面會講),暴力找出 \(p\) 的原根然后 BSGS 找出 \(g^a\equiv n\pmod{p}\),若 \(a\) 為奇數那無解,否則返回 \(g^{a/2}\) 即可,時間復雜度根號。
顯然這個做法並不能讓我們滿足。下面講一個更快的做法——Cipolla 算法。考慮隨機在 \([0,p-1]\) 中產生一個數 \(a\),設 \(w=a^2-n\),那么如果 \(w\) 為模 \(p\) 意義下的二次非剩余,\((a+\sqrt{w})^{\frac{p+1}{2}}\) 就是滿足條件的一個解。
證明:考慮 \((a+\sqrt{w})^p\) 的展開式,\((a+\sqrt{w})^p=\sum\limits_{i=0}^p\dbinom{p}{i}a^i(\sqrt{w})^{p-i}\)(有組合數學內味兒了),而 \(\dbinom{p}{i}\equiv 0\pmod{p}(i\in [1,p-1])\)(這個在證明 Lucas 定理的時候用到過,不記得了可以往前翻翻),故 \((a+\sqrt{w})^p\equiv a^p+(\sqrt{w})^p\pmod{p}\),而根據費馬小定理 \(a^p=a·a^{p-1}\equiv a\pmod{p}\),而 \((\sqrt{w})^p=\sqrt{w}·(\sqrt{w})^{p-1}=\sqrt{w}·w^{\frac{p-1}{2}}\equiv-\sqrt{w}\pmod{p}\),故 \((a+\sqrt{w})^p\equiv a-\sqrt{w}\pmod{p}\),於是有 \((a+\sqrt{w})^{p+1}=(a+\sqrt{w})·(a+\sqrt{w})^p\equiv(a+\sqrt{w})(a-\sqrt{w})=a^2-w=(a^2-(a^2-n))=n\pmod{p}\),故 \((a+\sqrt{w})^{\frac{p+1}{2}}\) 為滿足 \(x^2\equiv n\pmod{p}\) 的 \(x\)。
但你可能會疑惑:\(w\) 不是模 \(p\) 意義下的二次非剩余嗎?哪兒來的 \(\sqrt{w}\) 啊?其實這玩意兒相當於擴展了數集的定義。我們記 \(\mathbb{Z}_w=\{a+b\sqrt{w}|a,b\in[1,p-1]\}\),在此基礎上定義了乘法運算 \((a+b\sqrt{w})(c+d\sqrt{w})=(ac+bdw)+(ad+bc)\sqrt{w}\),類似於復數的乘法運算,可通過手寫復數類+快速冪來實現計算 \((a+\sqrt{w})^{\frac{p+1}{2}}\)。
由於那就是 \([1,p-1]\) 內二次剩余的的個數恰好為 \(\frac{p-1}{2}\),故期望隨機的次數為 \(2\),總復雜度 \(\log p\)。
int n,mod,w;
unsigned int rng60(){
static unsigned int seed=19260817;
seed^=seed<<17;seed^=seed<<10;seed^=seed>>7;
return seed;
}
int qpow(int x,int e){
int ret=1;
for(;e;e>>=1,x=1ll*x*x%mod) if(e&1) ret=1ll*ret*x%mod;
return ret;
}
struct comp{
int x,y;
comp(){x=y=0;}
comp(int _x,int _y){x=_x;y=_y;}
comp operator *(const comp &rhs){
return comp((1ll*x*rhs.x+1ll*y*rhs.y%mod*w%mod)%mod,(1ll*x*rhs.y+1ll*y*rhs.x)%mod);
}
};
void solve(){
scanf("%d%d",&n,&mod);
if(!n) puts("0");
else if(qpow(n,(mod-1)/2)==mod-1) puts("Hola!");
else{
while(1){
int x=rng60()%mod;w=(1ll*x*x-n+mod)%mod;
if(qpow(w,(mod-1)/2)==mod-1){
int pw=(mod+1)/2;
comp mul(1,0),v(x,1);
for(;pw;pw>>=1,v=v*v) if(pw&1) mul=mul*v;
if(mul.x<mod-mul.x) printf("%d %d\n",mul.x,mod-mul.x);
else printf("%d %d\n",mod-mul.x,mul.x);
break;
}
}
}
}
例題:
暫時咕着了。。。
歐拉函數與歐拉定理
歐拉函數
定義 \(\varphi(n)\) 為滿足 \(a\in[1,n]\) 且 \((a,n)=1\) 的 \(a\) 的個數。特別地,\(\varphi(1)=1\)。
譬如當 \(n=12\) 時,\(1\sim 12\) 中有 \(1,5,7,11\) 四個數與 \(12\) 互質,故 \(\varphi(12)=4\)。
積性函數
簡單講一下什么是積性函數。
一個函數 \(f:\mathbb{N}*\to\mathbb{N}*\) 被稱為積性函數,當且僅當 \(\forall (x,y)=1,f(xy)=f(x)f(y)\)。
這個函數又被稱為完全積性函數,如果 \(\forall x,y\in\mathbb{N}*,f(xy)=f(x)f(y)\),也就是少了 \((x,y)=1\) 這個條件上式依然成立。
顯然完全積性函數 \(\in\) 積性函數。
歐拉函數的性質
下面列出了歐拉函數的幾個性質:
-
若 \(p\) 為質數,則 \(\varphi(p)=p-1\)
證明:由於 \(p\) 為質數,則顯然 \([1,p-1]\) 中的所有數都與 \(p\) 互質,故 \(\varphi(p)=p-1\)
-
若 \(p\) 為質數,\(k\in\mathbb{N}*\),則 \(\varphi(p^k)=(p-1)\times p^k\)
證明:顯然,與 \(p^k\) 不互質的數都是 \(p\) 的倍數,而 \([1,p^k]\) 中共有 \(p^{k-1}\) 個 \(p\) 的倍數,故 \(\varphi(p^k)=(p-1)\times p^{k-1}\)。
-
設 \(n\) 的質因數分解形式為 \(n=p_1^{k_1}·p_2^{k_2}\dots p_m^{k_m}\),則 \(\varphi(n)=n\times\prod\limits_{i=1}^m\dfrac{p_i-1}{p_i}\)。
證明:首先有一個很顯然的結論,那就是如果一個數 \(m\) 與 \(n\),那么 \(m\) 至少與 \(n\) 有一個公共的質因子。我們考慮用一個“篩”的思想將 \(1\sim n\) 中所有與 \(n\) 互質的數一一篩去。我們先將 \([1,n]\) 中所有數標記為“與 \(n\) 互質”,先考慮 \(p_1\),顯然 \(1\sim n\) 中有 \(\dfrac{n}{p_1}\) 個數與 \(n\) 有公共的質因子 \(p_1\),將這些數全部篩去,還剩 \(n\times\dfrac{p_1-1}{p_1}\) 個數,再考慮 \(p_2\),由於 \((p_1,p_2)=1\),故剩余的數中模 \(p_2\) 余 \(0,1,2,\dots,p_2-1\) 的數的個數都是相等的,篩去了 \(n\times\dfrac{p_1-1}{p_1}\times\dfrac{1}{p_2}\) 個數,還剩 \(n\times\dfrac{p_1-1}{p_1}\times\dfrac{p_2-1}{p_2}\) 個數,接下來考慮 \(p_3,p_4,\dots\),最后還剩 \(n\times\prod\limits_{i=1}^m\dfrac{p_i-1}{p_i}\) 個數。顯然與 \(n\) 互質的數永遠不會被篩去,與 \(n\) 不互質的某個數 \(m\),假設它與 \(n\) 有 \(k\) 個公共質因子 \(p_{i_1},p_{i_2},\dots,p_{i_k}\),其中 \(i_1<i_2<\dots<i_k\),那么它恰好會在 \(p_{i_1}\) 處篩去一次,故剩余的數包含且恰好包含了 \([1,n]\) 中所有與 \(n\) 互質的數,於是有 \(\varphi(n)=n\times\prod\limits_{i=1}^m\dfrac{p_i-1}{p_i}\)
-
\(\varphi(n)\) 為積性函數但不是完全積性函數,即 \(\forall (x,y)=1,\varphi(xy)=\varphi(x)\varphi(y)\)
假設 \(x\) 的質因數為 \(p_1,p_2,\dots,p_{\alpha}\),\(y\) 的質因數為 \(q_1,q_2,\dots,q_{\beta}\),由於 \((x,y)=1\),\(p_i\neq q_j\),故 \(xy\) 中恰好包含了 \(p_1,p_2,\dots,p_{\alpha},q_1,q_2,\dots,q_{\beta}\) 這 \(\alpha+\beta\) 個質因數,於是 \(\varphi(xy)=xy\times\prod\limits_{i=1}^{\alpha}\dfrac{p_i-1}{p_i}\times\prod\limits_{i=1}^{\beta}\dfrac{q_i-1}{q_i}=(x\times\prod\limits_{i=1}^{\alpha}\dfrac{p_i-1}{p_i})\times(y\times\prod\limits_{i=1}^{\beta}\dfrac{q_i-1}{q_i})=\varphi(x)\varphi(y)\)
而 \(\varphi(4)=2,\varphi(6)=2,\varphi(24)=8\neq \varphi(4)\times\varphi(6)\),故 \(\varphi(n)\) 為積性函數但不是完全積性函數。
-
對於 \(x,y\in\mathbb{N}*\),若 \(x\mid y\) 則 \(\varphi(xy)=x\varphi(y)\)
證明:和上一個定理證明方法類似,假設 \(x\) 包含的質因子集合 \(S=\{p_1,p_2,\dots,p_{\alpha}\}\),\(y\) 包含的質因子集合為\(T=\{q_1,q_2,\dots,q_{\beta}\}\),由於 \(x\mid y\),必然有 \(S\subseteq T\),於是 \(xy\) 包含的質因子集合也為 \(T\),即 \(\varphi(xy)=xy\times\prod\limits_{i=1}^{\beta}\dfrac{q_i-1}{q_i}=x\times(y\times\prod\limits_{i=1}^{\beta}\dfrac{q_i-1}{q_i})=x\varphi(y)\)
-
\(\forall n>2,\varphi(n)\) 為偶數
證明:對於 \(m\leq n\) 且 \((m,n)=1\),必有 \((n-m,n)=1\),否則假設 \(n=ak,n-m=bk(k>1)\),則 \(m=(a-b)k\),\((m,n)=k>1\),矛盾!而對於奇數 \(n\),不存在整數 \(m\) 使得 \(n-m=m\),對於 \(n>2\) 的偶數,雖然 \(n-\dfrac{n}{2}=\dfrac{n}{2}\),但 \((\dfrac{n}{2},n)>1\)。故所有 \(\leq n\) 與 \(n\) 互質的數都可以兩兩配對,原命題成立。
-
\(\color{Red}{\sum\limits_{d\in[1,n],d|n}\varphi(d)=n}\)(very important!)
證明:考慮 \(1\sim n\) 中的某個數 \(x\),設 \(d=\gcd(n,x),n=n'd,x=x'd\),那么顯然有 \((n',x')=1,d|n,x'\leq n'\)。我們設 \(S_d=\{x|x\in [1,n],\dfrac{n}{\gcd(n,x)}=d\}\),那么顯然 \(x'\) 滿足 \(x'\leq d\) 且 \((x',d)=1\),並且對於所有 \(\gcd(x',d)=1\) 的 \(x'\) 都有 \(x'·\dfrac{n}{d}\in S_d\),故 \(|S_d|=\varphi(d)\),而對於 \(d\nmid n\),\(S_d=\varnothing\),也就是說對於任意 \(x\in [1,n]\) 都存在恰好一個 \(d|n\) 使得 \(x\in S_d\),故 \(\sum\limits_{d|n}|S_d|=n\),即 \(\sum\limits_{d\in[1,n],d|n}\varphi(d)=n\)
求歐拉函數的方法
一種求歐拉函數的方法是直接 \(\mathcal O(\sqrt{n})\) 地枚舉 \(n\) 的質因子並用 \(\varphi(n)=n\times\prod\limits_{i=1}^m\dfrac{p_i-1}{p_i}\) 直接計算,一般用於處理 \(10^9\) 級別的數據。
int phi(int x){
int tmp=x,ret=x;
for(int i=2;i*i<=x;i++) if(tmp%i==0){
ret=ret/i*(i-1);
while(tmp%i==0) tmp/=i;
} if(tmp>1) ret=ret/tmp*(tmp-1);
return ret;
}
還有一種方法是用線性篩的方法在線性時間內求出某個數之內所有數的歐拉函數,大體框架和和線性篩類似,一般在值域較小時用於預處理,具體見代碼吧:
bitset<MAXV+5> vis;
int pr[MAXV/10+5],prcnt=0,phi[MAXV+5];
void sieve(int n){
phi[1]=1;
for(int i=2;i<=n;i++){
if(!vis[i]){pr[++prcnt]=i;phi[i]=i-1;}//性質 1:對於質數 p,phi[p]=p-1
for(int j=1;j<=prcnt&&pr[j]*i<=n;j++){
vis[pr[j]*i]=1;
if(i%pr[j]==0){phi[pr[j]*i]=phi[i]*pr[j];break;}//性質 5:對於 x|y,phi(xy)=xphi(y)
else phi[pr[j]*i]=phi[pr[j]]*phi[i];//性質 4:對於 (x,y)=1,phi(xy)=phi(x)phi(y)
}
}
}
最后說句閑話,\(n\) 以內質數個數大約是 \(\dfrac{n}{\ln n}\) 級別的,具體為什么我不太清楚,反正就當個結論記着罷。
歐拉定理
真·歐拉 nb,今天上午 XES 學了個公式叫 \(v-e+f=2\) 也叫歐拉定理來着的?
(數論中的)歐拉定理說的是這樣一件事:對於 \((a,m)=1\) 有 \(a^{\varphi(m)}\equiv 1\pmod{m}\)
當 \(m\) 為質數時有 \(a^{m-1}\equiv 1\pmod{m}\),此時該定理又被稱為“費馬小定理”。
證明:將 \([1,m]\) 中與 \(m\) 互質的數記作集合 \(S\),再記集合 \(T=\{ax\bmod m|x\in S\}\)。
先證明兩個 Lemma。
Lemma 1:\(T\) 中不存在相同的數,因為假設 \(\exist x,y\in S\) 使得 \(ax\equiv ay\pmod{m}\),那么就有 \(a(x-y)\equiv 0\pmod{m}\)。而 \((a,m)=1\),故 \(x\equiv y\pmod{m}\)。又 \(x,y\in [1,m],x\neq y\),故 \(x,y\) 模 \(m\) 不同余,矛盾!
Lemma 2:\(\forall x\in T,(x,m)=1\)。因為對於 \(x\in S\),由已知 \((a,m)=1,(x,m)=1\),故 \(a,x\) 與 \(m\) 不含公共質因子,於是 \((ax,m)=1\),得證。
由兩個引理可知 \(|T|=|S|=\varphi(m)\),且 \(T\) 中的數均與 \(m\) 互質。而 \([1,m]\) 中與 \(m\) 互質的數有且僅有 \(\varphi(m)\) 個,故 \(S,T\) 組成完全相同。於是我們有 \(\prod\limits_{(x,m)=1}x\equiv\prod\limits_{(x,m)=1}ax\pmod{m}\),記 \(P=\prod\limits_{(x,m)=1}x\bmod m\),則 \(P\equiv a^{\varphi(m)}P\pmod{m}\),顯然 \(P\neq 0\),故 \(a^{\varphi(p)}\equiv 1\pmod{p}\)。得證。
注:這邊有的人會進入一個誤區,那就是有人認為循環節長度就是 \(\varphi(m)\),i.e.,最小的滿足 \(a^x\equiv 1\pmod{m},x>0\) 的 \(x\) 就是 \(\varphi(m)\),這個理解是錯誤的。我們就拿 \(a=2,m=7\) 舉例,\(2\) 的冪模 \(7\) 的余數分別為 \(1,2,4,1,2,4\dots\),我們發現循環節長度為 \(3\neq 6=\varphi(m)\)。實際上這里有一個定理,那就是這樣的 \(x\) 必定是 \(\varphi(m)\) 的約數,證明就考慮反證法,假設 \(x\nmid\varphi(m)\),那么顯然 \(\exist r,rx<\varphi(m)<(r+1)x\),這樣就有 \(a^{rx}=(a^x)^r\equiv 1\pmod{m}\),而由歐拉定理 \(a^{\varphi(m)}\equiv 1\pmod{m}\),故 \(a^{\varphi(m)-rx}\equiv 1\pmod{m}\),而根據 \(rx<\varphi(m)<(r+1)x\) 知 \(\varphi(m)-rx<x\),也就是說我們找到了更小的滿足 \(a^x\equiv 1\pmod{m}\) 的 \(x\),矛盾!
擴展歐拉定理
yet another 擴展xxx……
歐拉定理還能擴展到不互質的情況,具體來說:
說白了就是前 \(\varphi(m)\) 個還不一定進入循環節,后面每 \(\varphi(m)\) 個一循環(注意:這邊的 \(\varphi(m)\) 也未必是循環節長度)。
舉個例子就明白了,考察 \(14\) 的冪模 \(44\) 的值:\(1,14,20,4,16,36,20,4,16,36,\dots\)。
不難發現,前面有幾個未進入循環節,后面就每 \(4\) 個一循環了。
證明:考慮設 \(a=p_1^{k_1}·p_2^{k_2}·p_3^{k_3}\dots p_t^{k_t}\),我們只需對每個 \(p_i\) 證出 \((p_i^{k_i})^x\equiv (p_i^{k_i})^{x\bmod\varphi(m)+\varphi(m)}\pmod{p_i^{k_i}}\),后面的部分可用 CRT 說明。
考慮某個質因子 \(p\),設 \(m=s·p^k\),\((s,p)=1\)。根據歐拉定理有 \(p^{\varphi(s)}\equiv 1\pmod{s}\)。而根據 \((s,p^k)=1\) 可知 \(\varphi(m)=\varphi(s)\varphi(p^k)\),故 \(\varphi(s)\mid\varphi(m)\)。故 \(p^{\varphi(m)}\equiv 1\pmod{s}\)。根據同余的性質,同余號左右兩邊同乘 \(p^k\) 可得 \(p^{\varphi(m)+k}\equiv p^k\pmod{s·p^k}\)。而 \(s·p^k=m\),故 \(p^{\varphi(m)+k}\equiv p^k\pmod{m}\)。考慮某個 \(c\geq k\),顯然有 \(p^c=p^{c-k+k}=p^{c-k}·p^k\equiv p^{c-k}·p^{k+\varphi(m)}=p^{c+\varphi(m)}\)。於是我們得到了公式 \(\forall c\geq k,p^c\equiv p^{c+\varphi(m)}\pmod{m}\)。而顯然 \(k\leq\varphi(m)\)。故 \(p^x\equiv p^{x\bmod\varphi(m)+\varphi(m)}\)。兩邊同時 \(k\) 次方可得 \((p^k)^{x}\equiv (p^k)^{x\bmod\varphi(m)+k\varphi(m)}\pmod{p}\),得證。
原根與階
階
定義 \(a\) 在模 \(m\) 意義下的階為滿足 \(a^x\equiv 1\pmod{m}\) 的最小整數 \(x\),記作 \(\text{ord}_ma\),有的地方也會記作 \(\delta_ma\)。顯然 \(a\) 在模 \(m\) 意義下的階存在的充要條件為 \((a,m)=1\),這個在 BSGS 的地方就證過了。
有關階的一個很重要的結論是 \(a^x\equiv 1\pmod{m}\Leftrightarrow\text{ord}_ma\mid x\)
后者推前者是相當容易的,這里就不再贅述了。前者推后者事實上我們在歐拉定理的部分已經證過了,這里再重復一遍,假設 \(\text{ord}_ma\nmid x\),那么顯然 \(\exist r,r\text{ord}_ma<x<(r+1)\text{ord}_ma\),這樣就有 \(a^{r\text{ord}_ma}=(a^{\text{ord}_ma})^r\equiv 1\pmod{m}\),而 \(a^x\equiv 1\pmod{m}\),故 \(a^{x-r\text{ord}_ma}\equiv 1\pmod{m}\),而根據 \(r\text{ord}_ma<x<(r+1)\text{ord}_ma\) 知 \(x-r\text{ord}_ma<\text{ord}_ma\),也就是說我們找到了更小的滿足 \(a^x\equiv 1\pmod{m}\) 的 \(x\),與階的定義矛盾!
原根
定義一個數 \(g\) 為模 \(m\) 意義下的原根,當且僅當 \(\text{ord}_gm=\varphi(m)\)。
它還有一個等價的定義,那就是 \(g^1,g^2,g^3,\cdots,g^{\varphi(m)}\) 兩兩模 \(m\) 不同余。
證明:充分性:由於 \(g^1,g^2,g^3,\cdots,g^{\varphi(m)}\) 兩兩模 \(m\) 不同余,必然有 \(\forall x\in[1,\varphi(m)),g^x\not\equiv g^{\varphi(m)}=1\),由階的定義可知 \(\text{ord}_gm=\varphi(m)\)。必要性:反證法,假設 \(\exist x,y\in[1,\varphi(m)],x<y,g^x\equiv g^y\pmod{m}\),由 \(g\) 在模 \(m\) 意義下的階存在可知 \((g,m)=1\),故 \((g^x,m)=1\),在同余等式 \(g^x\equiv g^y\pmod{m}\) 兩邊同乘 \(g^{-x}\) 可得 \(g^{y-x}\equiv 1\pmod{m}\),而由 \(x,y\in [1,\varphi(m)]\) 知 \(y-x<\varphi(m)\),與階的定義矛盾!故假設不成立,原命題成立。
原根的存在性
並不是所有的模數 \(m\) 都存在原根,事實上只有 \(2,4\) 及形如 \(p^k,2p^k\) 的數才存在原根(其中 \(p\) 為奇質數,\(k\in\mathbb{N}^+\)),至於為什么我也不太清楚,反正就當個定理用着就行了。
原根的判定
對於某數 \(a\),如果它為模 \(m\) 意義下的原根,那么首先必須有 \((a,m)=1\),否則就沒什么階可談了,就更不用說原根了。
其次根據階的定理,\(\forall (x,m)=1,\text{ord}_mx\mid\varphi(m)\),所以如果 \(a\) 不是模 \(m\) 意義下的原根,那么必然有 \(\text{ord}_ma\) 為 \(\varphi(m)\) 的真因子,故我們枚舉 \(\varphi(m)\) 真因子 \(p\),如果 \(\exist a^p\equiv 1\pmod{m}\) 那么意味着 \(a\) 不是模 \(m\) 意義下的原根,否則 \(a\) 為模 \(m\) 意義下的原根。
這里有一個小小的優化,那就是只用枚舉 \(\varphi(m)\) 的所有質因子 \(p\) 並檢驗 \(a^{\varphi(m)/p}\equiv 1\pmod{m}\) 即可,正確性顯然。
求一個數全部原根的做法
首先我們找出 \(m\) 的最小原根 \(g\),這里再一次不加證明地拋出一個定理:一個數最小原根的大小是 \(\sqrt[4]{m}\) 級別的,故暴力循環 \(+\) 按照上面所說的方式判定原根的復雜度是 ok 的,至於為什么我也不知道,btw 這種事情你管這么多干嘛呢,就當個定理記在腦子里罷/wq
下面要證明的一件事是:\(m\) 的原根個數為 \(\varphi(\varphi(m))\),並且都可以表示為 \(g^k\bmod m,k\in[1,\varphi(m)],(k,\varphi(m))=1\) 的形式。
證明:首先很明顯的一點是 \(g^1,g^2,\dots,g^{\varphi(m)}\) 兩兩模 \(m\) 不同余,故這 \(\varphi(\varphi(m))\) 個數兩兩互不相同。
其次,我們先證明一個引理,\(a^x\equiv a^y\pmod{m}\Leftrightarrow x\equiv y\pmod{\text{ord}_ma}\)。充分性:不妨設 \(x<y\),因為 \(x\equiv y\pmod{\text{ord}_ma}\),必有 \(y-x=k\text{ord}_ma,k\in\mathbb{Z}\),故 \(a^{y-x}=a^{\text{ord}_mak}=(a^{\text{ord}_ma})^k\equiv 1\pmod{m}\),兩邊同乘 \(a^x\) 可得 \(a^x\equiv a^y\pmod{m}\)。必要性:由於 \(\text{ord}_ma\) 有意義,\((a,m)=1\),故 \((a^x,m)=1\),兩邊同乘 \(a^x\) 的逆元可得 \(1\equiv a^{y-x}\pmod{m}\),根據階的定義知 \(\text{ord}_ma\mid y-x\),得證。
最后考慮怎樣證明原命題。一方面,假設 \(\exist k\in[1,\varphi(m)],(k,\varphi(m))=1\) 且滿足 \(\exist x,y\in [1,\varphi(m)],x\ne y\) 使得 \((g^{k})^x\equiv (g^{k})^y\pmod{m}\),那么根據引理得 \(kx\equiv ky\pmod{\text{ord}_mg}\),而由 \(g\) 為 \(m\) 的原根知 \(\text{ord}_mg=\varphi(m)\),故 \(\varphi(m)\mid k(y-x)\),而 \((k,\varphi(m))=1\),故 \(\varphi(m)\mid y-x\),又 \(x,y\in [1,\varphi(m)],x\ne y\) 可推出矛盾,故所有可表示為 \(g^k\bmod m\) 的數,其中 \(k\in[1,\varphi(m)],(k,\varphi(m))=1\),均為 \(m\) 的原根。另一方面,\(\forall k'\in[1,\varphi(m)],(k',\varphi(m))>1\),設 \(d=(k',\varphi(m)),k'=k''d\),那么 \((g^{k'})^{\frac{\varphi(m)}{d}}=(g^{k''d})^{\frac{\varphi(m)}{d}}=(g^{\varphi(m)})^{k''}\equiv 1\pmod{m}\),故 \(g^{k'}\) 不是 \(m\) 的原根,得證。
例題:
咕咕咕咕咕咕咕咕咕咕咕咕,一排鴿子緩緩飛過:
🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊🕊
整除分塊
一個很實用的 trick 哦
首先看一道例題:CF616E Sum of Remainders,題目要我們求 \(\sum\limits_{i=1}^mn\bmod i\)。
老司機一看到 \(\bmod\) 就會將其替換為除法,即 \(i\bmod j=i-j\times\lfloor\dfrac{i}{j}\rfloor\)
於是原式可化為 \(\sum\limits_{i=1}^mn-i\times\lfloor\dfrac{n}{i}\rfloor=nm-\sum\limits_{i=1}^mi\times\lfloor\dfrac{n}{i}\rfloor\)
可是這東西暴力計算還是不行啊。。。
注意到本題數據范圍 \(10^{13}\) 給得非常微妙,應該是放根號算法過去的,於是我們考慮根號分治。
回憶起小學奧數時學過的一個性質:當 \(i\) 很小的時候,\(\lfloor\dfrac{n}{i}\rfloor\) 差距很大,當 \(i\) 很大的時候,\(\lfloor\dfrac{n}{i}\rfloor\) 非常緊湊。
那么這個“很小”和“很大”的分界點究竟是什么呢?就是我們期待的 \(\sqrt{n}\) 了。
於是考慮一個暴力做法:對於 \(i\leq\sqrt{n}\) 暴力計算顯然時間復雜度不會炸,對於 \(i>\sqrt{n}\) 枚舉 \(\lfloor\dfrac{n}{i}\rfloor\) 的值,顯然滿足 \(\lfloor\dfrac{n}{i}\rfloor=x\) 的 \(i\) 會構成一個區間 \([l,r]\)。由於這個區間中 \(\lfloor\dfrac{n}{i}\rfloor\) 的值相同,所以我們直接用 \(\lfloor\dfrac{n}{i}\rfloor\times\sum\limits_{j=l}^rj\) 就可以計算這一段的貢獻了,后面那東西顯然可以在常數時間內求出。
事實上我們並不用把這個“根號”體現在程序中,考慮把 \(\lfloor\dfrac{n}{i}\rfloor\) 的表列出來看看它長啥樣,比方說 \(n=10\),那么 \(\lfloor\dfrac{n}{i}\rfloor\) 的值分別為 \(10,5,3,2,2,1,1,1,1,1\),我們發現這些數構成了一個個“塊”,這也就是“整除分塊”名字的由來。顯然塊的個數不會超過 \(2\sqrt{n}\),於是我們考慮改為枚舉塊。我們記錄兩個變量 \(l,r\) 表示當前塊的左端點、右端點,這里有一個結論是對於左端點為 \(l\) 的塊,它的右端點 \(r=\lfloor\dfrac{n}{\lfloor\dfrac{n}{l}\rfloor}\rfloor\)。
簡單證明一下:設 \(x\) 滿足 \(\lfloor\dfrac{n}{x}\rfloor=\lfloor\dfrac{n}{l}\rfloor\),那么顯然 \(\dfrac{n}{x}\geq\lfloor\dfrac{n}{l}\rfloor\),兩邊同時取倒數可得 \(\dfrac{x}{n}\le\dfrac{1}{\lfloor\dfrac{n}{l}\rfloor}\),兩邊再同乘 \(n\) 可得 \(x\le\dfrac{n}{\lfloor\dfrac{n}{l}\rfloor}\),也就是說 \(x>\dfrac{n}{\lfloor\dfrac{n}{l}\rfloor}\) 都不符合題意。至於充分性……假設 \(v=\lfloor\dfrac{n}{l}\rfloor\),設 \(n=pv+q(q<v)\),顯然 \(q<l\),因為 \(n-vl<l\),而 \(p\ge l\),故 \(q=n-vp<l\leq p\),故 \(v=\lfloor\dfrac{n}{p}\rfloor\),即 \(\lfloor\dfrac{n}{\lfloor\dfrac{n}{\lfloor\dfrac{n}{l}\rfloor}\rfloor}\rfloor=\lfloor\dfrac{n}{l}\rfloor\),得證。
大體代碼長這樣:
for(ll l=1,r;l<=min(n,m);l=r+1){
r=(n/(n/l));
計算貢獻
}
當然整除分塊還有一些變種:
- \(\sum\limits_{i=1}^mf(i)\lfloor\dfrac{n}{i}\rfloor\):類似於上面的情形,枚舉 \(\lfloor\dfrac{n}{i}\rfloor\) 所在的塊,然后求出 \(f(i)\) 的前綴和來計算貢獻。
- \(\sum\limits_{i=1}^x\sum\limits_{j=1}^y\lfloor\dfrac{n}{i}\rfloor\lfloor\dfrac{m}{i}\rfloor\):也是加個小小的改動,將 \(r\) 的值設為 \(r=\min(\lfloor\dfrac{n}{\lfloor\dfrac{n}{l}\rfloor}\rfloor,\lfloor\dfrac{m}{\lfloor\dfrac{m}{l}\rfloor}\rfloor)\),這樣能保證 \([l,r]\) 中所有數 \(\lfloor\dfrac{n}{i}\rfloor,\lfloor\dfrac{m}{i}\rfloor\) 值都是相同的,並且塊的個數還是根號級別的。
例題:
咕咕咕