總結一波數論基礎知識。。。。大佬勿入
拓展歐幾里得:
這麼水,直接上代碼比較方便:
LL ex_gcd(LL a,LL b,LL &x,LL &y) //求解一個方程:ax+by=gcd(a,b)的一組特解。
{LL x1,y1,d;
if(b==0) //若b爲0顯然此時x=1,y=0
{x=1;y=0;return a;
}
d=ex_gcd(b,a%b,x1,y1);//將求解轉化爲求解方程:bx+(a%b)y=gcd(b,a%b)=gcd(a,b),順便求一下gcd(a,b)
x=y1;y=x1-a/b*y1; //將得到的解轉化一下。
return d;
}
乘法逆元
定義:記數 在模 意義下的乘法逆元爲 ,即滿足模方程:
逆元在求模數時十分有用。
注:有的數可能沒有乘法逆元
求法1:
根據歐拉定理可得:對於任意整數 ,均存在:
故: 所以任意數 模 意義下的的乘法逆元爲:
用快速冪求解即可。時間複雜度:
注:一般只用於 素數時,歐拉函數難得算,但是素數時 ,考試時一般用的是素數
~~不用貼代碼了吧。。。水的很~~
求法2:
我們將模方程換一個方式寫下:
移項得:
其中 爲未知數,是不是很像方程:ax+by=1?
於是就可以用拓展歐幾里得求解 如果不互質,要除掉gcd。
組合數
還是解釋一下吧:
好了就這樣吧。
求法1:數據小時打表啦
用遞推式遞推即可。
for(i=0;i<=2000;i++)c[i][0]=1;
for(i=1;i<=2000;i++)
for(LL j=1;j<=i;j++)
c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
求法2,求解的組合數中有炒雞大的數,比模數還大:盧卡斯定理
盧卡斯定理很難說,直接上代碼:
LL lucas(int x,int y){
if(x<mod&&y<mod)return C(x,y);
return (C(x%mod,y%mod)+C(x/mod,y/mod))%mod;
}
很簡單對不對?剩下的可以用打表法預處理或者預處理階乘求解即可。
求法3沒有辦法的辦法:線性求C:
根據 線性求,時間複雜度 ,如果要取餘還要求個逆元就是 。
void getc(int x,int y){
LL i,ans=1;
for(i=1;i<=x;i++)ans=((ans*(y-i+1))%mod*getni(i))%mod;
}
歐拉線性篩模板
還是看代碼吧:在莫比烏斯反演中非常有用
int pi[100010],prime[100010];
bool mark[100010]
void getpi(){//歐拉線性篩,求解歐拉函數與質數
int cnt=0,i,j;
for(i=2;i<=n;i++){
if(!mark[i]){
prime[++cnt]=i;//若當前數沒被篩到,則它是質數。
pi[i]=i-1;//質數的歐拉函數是該數減1
}
for(j=0;j<cnt&&i*prime[j]<=n){
mark[i*prime[j]]=true;
if(i%prime[j]==0){
pi[i*prime[j]]=phi[i]*prime[j];
break;
}
else pi[i*prime[j]]=phi[i]*(prime[j]-1);//分類討論枚舉
}
}
}
時間複雜度 時間用的很少的暴力篩。
順便一提:歐拉函數與歐拉定理
歐拉函數: 爲比n小且與n互質的數字個數。它的性質多得不得了。
歐拉定理:
這個沒多大用處的。但是,它可以壓縮快速冪的計算複雜度:
條件太苛刻了,於是又有拓展:
中國剩餘定理:
對於一個數 ,對於所有 滿足:
則它的最小正整數解爲:
令 , , 爲 在模 意義下的逆元。
則