數論學習

歐拉函數篩法

歐拉函數: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];

 

posted @ 2018-11-03 21:27  Lin88  阅读(99)  评论(0编辑  收藏  举报