各种线性筛板子

线性筛集合

1.线性筛素数

lld p[N];
void euler(int n) {
	bool vis[N]; memset(vis, 0, sizeof(vis));
	for(int i = 2; i <= n; i++) {
		if(!vis[i]) {
			vis[i] = true; p[++tot] = i;
		}
		for(int j = 1; i * p[j] <= n && j <= tot; j++) {
			vis[i * p[j]] = true;
		}
	}
}

2.线性筛欧拉函数 \(\phi\)

根据 \(\phi(n)\) 的性质:

1.当n为质数时,\(\phi(n) = n - 1\)

2.若m,n互质,\(\phi(n \cdot m) = \phi(n) \cdot \phi(m)\)

3.若m为质数,\(\phi(n \cdot m) = \phi(n) \cdot m\)

lld phi[N];
void euler(lld n) {
	bool vis[N]; memset(vis, 0, sizeof(vis));
	lld p[N]; memset(p, 0, sizeof(p));
	int tot = 0; phi[1] = 1;
	for(int i = 2; i <= n; i++) {
		if(!vis[i]) {
			vis[i] = true;
			p[++tot] = i; phi[i] = i - 1;
		}
		for(int j = 1; j <= tot && p[j] * i <= n; j++) {
			vis[p[j] * i] = true;
			if(i % p[j] != 0) phi[i * p[j]] = phi[i] * phi[p[j]];
			else {
				phi[i * p[j]] = phi[i] * p[j]; break;
			}
		}
	}
}

一个关于欧拉函数的小性质:
定义 \(f(n)\) 为小于等于n的数中,与n互质的所有数的和,则:
\(f(n) = \frac{\phi(n) \cdot n}{2}\)

证明:\(gcd(n, i) = gcd(n, n - i)\)

3.线性筛莫比乌斯函数 \(\mu\)

根据 \(\mu(n)\) 性质:

1.\(\mu(1) = 1\)

2.当n是k个不同素数之积时,\(\mu(n) = (-1)^k\)

3.当n存在指数大于1的质因子时,\(\mu(n) = 0\)

lld mu[N];
void euler(lld n) {
	lld p[N]; memset(p, 0, sizeof(p));
	bool vis[N]; memset(vis, 0, sizeof(vis));
	mu[1] = 1; int tot = 0;
	for(int i = 2; i <= n; i++) {
		if(!vis[i]) {
			p[++tot] = i; vis[i] = true;
			mu[i] = -1;
		}
		for(int j = 1; j <= tot && p[j] * i <= n; j++) {
			vis[p[j] * i] = true;
			if(i % p[j] == 0) mu[i * p[j]] = 0;
			else mu[i * p[j]] = mu[i] * (-1);
		}
	}
}

4.线性筛约数个数

\(d(i)\) 表示i的约数个数,\(las(i)\) 表示i最小的质因子的指数
设i为任意一个数,\(p[j]\) 为已筛出的质数

1.若i为质数,则\(d(i) = 2, las(2) = 1\)

2.当 \(i \mod p[j] != 0\)时,\(d(i \cdot p[j]) = d(i) \cdot d(p[j]), las(i \cdot p[j]) = 1\)

3.当 \(i \mod p[j] = 0\)时, \(d(i \cdot p[j]) = d(i)/(las(i) + 1) * (las(i) + 2)\),

\(las(i \cdot p[j]) = las(i) + 1\)

void euler(){
	memset(vis, 0, sizeof(vis)); d[1] = 1;
	for(int i = 2; i <= n; i++) {
		if(!vis[i]) {
			vis[i] = true; p[++tot] = i;
			d[i] = 2; las[i] = 1;
		}
		for(int j = 1; j <= tot && i * p[j] <= n; j++){
			vis[i * p[j]] = true;
			if(i % p[j] == 0){
				d[i * p[j]] = d[i] / (las[i] + 1) * (las[i] + 2);
				las[i * p[j]] = las[i] + 1; break;
			}
			else{
				d[i * p[j]] = d[i] * d[p[j]];
				las[i * p[j]] = 1;
			}
		}
	}
}

5.线性筛约数和

已知:\(sd(i) = (1 + p_1 + p_1^2 +...+p_1^{r_1}) \cdot (1 + p_2 + p_2^2 +...+p_2^{r_2}) \cdot ... \cdot (1 + p_k + p_k^2 +...+p_k^{r_k})\)

\(sd(i)\) 表示i的约数和,\(num(i)\) 表示最小的一项 \((1 + p_1 + p_1^2 +...+p_1^{r_1})\)

1.若i为质数,\(sd(i) = i + 1, num(i) = i + 1\)

2.若 \(i \mod p[j] != 0\), \(sd(i \cdot p[j]) = sd(i) \cdot sd(p[j]), num(i \cdot p[j]) = 1 + p[j]\)

3.若 \(i \mod p[j] = 0\), \(sd(i \cdot p[j]) = sd(i) / num(i) \cdot (num(i) \cdot p[j] + 1), num(i \cdot p[j]) = num(i) \cdot p[j] + 1\)

void euler() {
	bool vis[N]; memset(vis, 0, sizeof(vis));
	lld p[N]; memset(p, 0, sizeof(p));
	int tot = 0; num[1] = 1; sd[1] = 1;
	for(int i = 2; i <= n; i++) {
		if(!vis[i]) {
			vis[i] = true; p[++tot] = i;
			num[i] = 1 + i; sd[i] = 1 + i;
		}
		for(int j = 1; j <= tot && p[j] * i <= n; j++) {
			vis[i * p[j]] = true;
			if(i % p[j] != 0) {
				sd[i * p[j]] = sd[i] * sd[p[j]]; num[i * p[j]] = p[j] + 1;
			} else {
				num[i * p[j]] = num[i] * p[j] + 1;
				sd[i * p[j]] = sd[i] / num[i] * num[i * p[j]];
				break;
			}
		}
	}
}

posted @ 2021-01-21 02:04  Mcggvc  阅读(117)  评论(0编辑  收藏  举报