线性求欧拉函数

我们都知道欧拉筛又称线性筛,能在O(n)的时间复杂度内筛出n以内的所有质数,而我们只要在线性筛的代码上改良一下就能求出n以内所有数的欧拉函数了。
筛质数时,设外层在枚举%i%,内层枚举到$prime[j]$,这时有两种情况:

  1. $i\%prime[j]$不为$0$,也就是说,$i$与$j$互质,根据欧拉函数的积性可得$phi[i*prime[j]]=phi[i]*phi[prime[j]]$而这些是前面求出来的,可以直接拿来推。
  2. $i\%prime[j]$为$0$,也就是说,i内有一个质因子是$prime[j]$,不过没有关系,这只是在i的质因数分解$prime[j]$的指数加$1$,而不会影响$\phi (x)=x*\prod_{i=1}^n (1-\frac{1}{p_i})$的右边$\prod_{i=1}^n (1-\frac{1}{p_i})$的部分,所以我们只要用$i*prime[j]$乘上右边$\prod_{i=1}^n (1-\frac{1}{p_i})$,即可推出$phi[i * prime[j]]=i *  prime[j] * phi[i]/i=prime[j] * phi[i]$。

附上代码:
    

 1 int phi[];
 2 int notprime[],prime[];
 3 int cnt;
 4 void getphi(int n){
 5     notprime[0]=notprime[1]=1;
 6     phi[1]=0,phi[2]=1;
 7     for(int i=2;i<=n;++i){
 8         if(!primenot[i]){
 9             phi[i]=i-1;//质数的欧拉函数值为该质数减一
10             prime[++cnt]=i;
11         }
12         for(int j=1;j<=cnt&&prime[j]*i<=n;++j){
13             notprime[prime[j]*i]=1;
14             if(i%prime[j]) phi[prime[j]*i]=phi[prime[j]]*phi[i];//互质
15             else {//不互质
16                 phi[prime[j]*i]=prime[j]*phi[i];
17                 break;
18             }
19         }
20     }
21 }
posted @ 2019-08-07 08:36  Asika391  阅读(209)  评论(0编辑  收藏  举报