筛法相关

最近打模板,发现自己好像快要忘记欧拉函数怎么搞了,所以写一下备忘

质数筛法

艾氏筛

算法复杂度: $ O(nloglogn)$
算法实现:对于每个质数 $ x$, 标记 $ x imes x, x imes (x+1), cdots, [N / x] imes x$为合数
代码:

inline void era_prime() {
	m = 0;
	memset(NotPrime, 0, sizeof(NotPrime));
	for (int i = 2; i <= n; ++ i) {
		if (NotPrime[i]) continue;
		prime[++m] = i;
		for (int j = i; j <= n/i; ++ j) NotPrime[i * j] = 1;
	}
}

欧拉筛

算法复杂度: $ O(n)$
算法实现:保证每个合数只被筛一次
拓展:求欧拉函数,一个数的因子数
代码:

inline void euler_prime() {
	m = 0;
	memset(NotPrime, 0, sizeof(NotPrime));
	for (int i = 2; i <= n; ++ i) {
		if (!NotPrime[i]) prime[++m] = i;
		for (int j = 1; j <= m && i * prime[j] <= n; ++ j) {
			NotPrime[prime[j] * i] = 1;
			if (i % prime[j] == 0) break;
		}
	}
}

欧拉函数

定义和相关

参见博客浅谈欧拉函数

基于线性筛的算法

算法实现:基于积性函数的性质
代码:

inline void euler_prime() {
	m = 0;
	memset(NotPrime, 0, sizeof(NotPrime));
        phi[1] = 1;
	for (int i = 2; i <= n; ++ i) {
		if (!NotPrime[i]) {prime[++m] = i, phi[i] = i - 1;}
		for (int j = 1; j <= m && i * prime[j] <= n; ++ j) {
			NotPrime[prime[j] * i] = 1;
			if (i % prime[j] == 0) {phi[i * prime[j]] = phi[i] * prime[j];break;}
            else phi[i * prime[j]] = phi[i] * (prime[j] - 1);
		}
	}
}

莫比乌斯反演

参见博客莫比乌斯反演
莫比乌斯函数也是积性函数,所以可以用线性筛在(O(n))时间解决

void sieve() {
    fill(prime, prime + maxn, 1);
    mu[1] = 1, tot = 0;
    for (int i = 2; i < maxn; i++) {
        if (prime[i]) {
            prime[++tot] = i, mu[i] = -1;
        }
        for (int j = 1; j <= tot && i * prime[j] < maxn; j++) {
            prime[i * prime[j]] = 0;
            if (i % prime[j] == 0) {
                mu[i * prime[j]] = 0;
                break;
            } else {
                mu[i * prime[j]] = -mu[i];
            }
        }
    }
}
原文地址:https://www.cnblogs.com/Alessandro/p/9704871.html