筛素数
考虑如何筛出 $n$ 以内的所有素数
对于上面的算法
for (int i = 2; i <= n; i++) {
if (!vis[i]) p[++cnt] = i;
for (int j = 1; j <= cnt && i * p[j] <= n; j++) {
vis[i * p[j]] = true;
if (i % p[j] == 0) break;
}
}
筛欧拉函数
考虑到 $\varphi$ 函数有如下性质
-
对于 $\varphi(p),p\in Prime$
直接在筛出质数的同时求解即可, 。 -
对于 $\varphi(ap),p\in Prime$
在 $p_j|i$ 时, $\varphi(i\times p_j)=\varphi(i)\times p_j$, 。 -
对于 $\varphi(ab),\gcd(a,b)=1$
直接在筛去合数的时候 $\varphi(i\times p_j)=\varphi(i)\times \varphi(p_j)$, 。
for (int i = 2; i <= n; i++) {
if (!vis[i]) p[++cnt] = i, phi[i] = i - 1;
for (int j = 1; j <= cnt && i * p[j] <= n; j++) {
vis[i * p[j]] = true;
if (i % p[j] == 0) {
phi[i * p[j]] = phi[i] * p[j];
break;
}
phi[i * p[j]] = phi[i] * phi[p[j]];
}
}
筛不同质因子的个数
令 $\alpha(x)$ 表示 $x$ 不同质因子的个数
于是用与筛欧拉函数相似的方法
for (int i = 2; i <= n; i++) {
if (!vis[i]) p[++cnt] = g[i]= i, f[i] = 1;
for (int j = 1; j <= cnt && i * p[j] < N; j++) {
vis[i * p[j]] = true;
if (i % p[j] == 0) {
g[i * p[j]] = g[i] * p[j];
f[i * p[j]] = f[i / g[i]] + 1;
break;
}
g[i * p[j]] = p[j];
f[i * p[j]] = f[i] + 1;
}
}