数论函数学习笔记之线性筛
其实主要是想发一下线性筛的板子,包括线性筛质数,约数个数,欧拉函数和莫比乌斯函数。
有些也会有一点简单的证明。
线性筛质数就不说啦。
然后加一个筛欧拉函数。
当\(i\)为质数的时候,自然\(\varphi(i) = i - 1\)。
令\(n = mp\),
当\(p \nmid m\)的时候,有\(\varphi(n) = \varphi(m) * \varphi(p) = \varphi(m) * (p - 1)\)。
否则有\(\varphi(n) = \varphi(m) * p\)。
证明一下吧:
首先\(p \nmid m\)时,根据积性,\(\varphi(n) = \varphi(m) * (p - 1)\)。
考虑另一种情况,
若\(p \mid m\),令\(m = k * p ^ x\),这样保证了\(k, p\)互质。
所以
然后看等式右边:
(也不知道这算不算证明)
另一种证明\(\varphi(n) = \varphi(m) * p\)的方法是把\(\varphi(n)\)和\(\varphi(m)\)相除,并用\(\varphi(n) = n * \prod_{质数p|n} (1 - \frac{1}{p})\)打开,约分后就是\(p\)了。
至于筛莫比乌斯函数,就更简单了。
如果\(n\)为质数,则\(\mu(n) = -1\)。
若\(p \mid m\),则\(\mu(n) = 0\),
否则\(\mu(n) = - \mu(m)\)。
最后是筛约数个数。
首先得知道这几个理论基础:
1.记\(n = \prod p _ i ^ {a_i}\),那么\(n\)的约数个数为\(\prod (a_i + 1)\),就是枚举每一个约数选几个。
2.线筛的时候,每一个数是被他的最小素因子筛去,如果\(prime[j] \mid i\),那么\(prime[j]\)也是\(i\)的最小素因子。
我们令\(y[n]\)表示\(n\)的约数个数,\(d[n]\)表示\(n\)的最小素因子的个数。
那么,
1.如果\(n\)为质数,显然有\(y[n] = 2, d[n] = 1\)。
2.如果\(n\)为合数,令\(n = i *prime[j]\),
(1)如果\(prime[j] \nmid i\),那么\(d[n] = 1, y[n] = y[i] * y[prime[j]] = y[i] * 2\)(积性)。
(2)如果\(prime[j] \mid i\),那么\(n\)和\(i\)的最小素因子都是\(prime[j]\),且\(d[n] = d[i] + 1\)。这时候算约数个数,把原来的除掉,乘以新的贡献即可:\(y[n] = y[i] * \frac{d[i] + 2}{d[i] + 1}\)。
In void init()
{
mu[1] = ys[1] = phi[1] = 1;
for(int i = 2; i < maxn; ++i)
{
if(!v[i])
{
prim[++pcnt] = i, v[i] = i;
mu[i] = -1, phi[i] = i - 1;
ys[i] = 2, d[i] = 1;
}
for(int j = 1; j <= pcnt && i * prim[j] < maxn; ++j)
{
int k = i * prim[j];
v[k] = prim[j];
if(i % prim[j] == 0)
mu[k] = 0;
phi[k] = prim[j] * phi[i];
ys[k] = ys[i] / (d[i] + 1) * (d[i] + 2);
d[k] = d[i] + 1;
break;
}
else
{
mu[k] = -mu[i];
phi[k] = (prim[j] - 1) * phi[i];
ys[k] = (ys[i] << 1), d[k] = 1;
}
}
}
}