數論學習
歐拉函數篩法
歐拉函數:phi(i)為1到i之間與i互質的數的個數
1 int prime[N],phi[N],isprime[N];
2 void getpri()
3 {
4 int cnt=0;
5 phi[1]=1;
6 memset(isprime,0,sizeof(isprime));
7 for(int i=2;i<N;++i)
8 {
9 if(!isprime[i])
10 {
11 prime[cnt++]=i;
12 isprime[i]=i;//質數條件isprime[i]==i
13 phi[i]=i-1;//質數的phi=i-1
14 }
15 for(int j=0;j<cnt&&i*prime[j]<N;++j)
16 {
17 isprime[i*prime[j]]=prime[j];
18 if(prime[j]>=isprime[i])//保證只有i的最小質因數的把i篩掉
19 {
20 phi[i*prime[j]]=phi[i]*prime[j];//i與prime[j]不互質時
21 break;
22 }
23 else
24 phi[i*prime[j]]=phi[i]*(prime[j]-1);//i與prime[j]互質時
25 }
26 }
27 }
擴展Euclid
1 ll exgcd(ll a,ll b,ll &x,ll &y)
2 {
3 if(b==0)
4 {
5 x=1;
6 y=0;
7 return a;
8 }
9 else
10 {
11 ll ret=exgcd(b,a%b,y,x);
12 y-=a/b*x;
13 return ret;
14 }
15 }
逆元求法
一、Fermat 小定理
若模數為素數p,整數$x$的乘法逆元為 $x^{p-2}$,直接用快速冪求得
二、擴展Euclid
若模數$m$不為素數,但x與m互質時,需要用EXGCD求:
1 int x,y;
2 ll t=exgcd(x,m,x,y);
3 // x 即位所求
三、線性遞推求逆元
對於同一個模數p(prime),如果需要多次使用多個數的逆元,則可線性把一定範圍的逆元求出來。
1 int inv[N];
2 inv[1]=1;
3 for(int i=1;i<p;++i)
4 inv[i]=-(p/i)*inv[p%i];