线性筛及线性递推欧拉函数

首先是很常用的线性筛代码:

#define N 1000000
int n, cnt, vis[N+5], prime[N+5];
void sieve() {
    vis[1] = 1;
    for(int i = 2; i <= n; ++i) {
        if(!vis[i]) prime[++cnt] = i;
        for(int j = 1; j <= cnt && i*prime[j] <= n; ++j) {
            vis[i*prime[j]] = 1;
            if(i%prime[j]==0) break;
        }
    }
}

线性筛保证了每个合数只会被它的最小质因子筛掉,所以复杂度是近似\(O(n)\)的。

欧拉函数

定义:对正整数n,欧拉函数是小于或等于n的正整数中与n互质的数的数目(φ(1)=1)。
计算公式:

$\phi(x)=x\prod\limits_{i=1}^{n}(1-\frac{1}{p_i})$
其$p_i$为$x$的质因子。 性质:欧拉函数是积性函数(即$\phi(mn)=\phi(m)\phi(n)$,m,n互质) 我们考虑怎样在线性筛时顺便求出欧拉函数: 1.若$vis[i]=1$,说明$i$是质数,$phi[i]=i-1$ 2.若$prime[j]$整除$i$,说明$i*prime[j]$标准分解式中$prime[j]$的次数已经大于$1$了,根据欧拉函数的计算式,不难得出$phi[i*prime[j]]=phi[i]*prime[j]$ 3.若$prime[j]$不整除$i$,说明$i$与$prime[j]$互质,又因为$prime[j]$是质数,则$phi[i*prime[j]]=phi[i]*phi[prime[j]]$,进而推出$phi[i*prime[j]]=phi[i]*(prime[j]-1)$ 我们按照上式把线性筛改造一下就行了: ```cpp #define N 1000000 int n, cnt, vis[N+5], prime[N+5], phi[N+5]; void sieve() { vis[1] = phi[1] = 1; for(int i = 2; i <= n; ++i) { if(!vis[i]) prime[++cnt] = i, phi[i] = i-1; for(int j = 1; j <= cnt && i*prime[j] <= n; ++j) { vis[i*prime[j]] = 1; if(i%prime[j]==0) { phi[i*prime[j]] = phi[i]*prime[j]; break; } phi[i*prime[j]] = phi[i]*phi[prime[j]]; } } } ```
posted @ 2018-10-14 23:27  dummyummy  阅读(417)  评论(0编辑  收藏  举报