线性筛筛一般积性函数
线性筛筛一般积性函数
前置芝士
线性筛、积性函数
有用的结论
设 \(f(x)\) 和 \(g(x)\) 都是积性函数,则 \(h(x) = f(x) \cdot g(x)\) 也是积性函数
设 \(f(x)\) 和 \(g(x)\) 都是积性函数,则 \(h(x \cdot y)=\sum\limits_{x\cdot y=n}f(x) \cdot g(y)\) 也是积性函数
How to do
给定一个积性函数 \(f(x)\)
要求能快速计算 \(f(p)\) 和 \(f(p^{k})\) 其中 \(p\) 为质数
对于每个数 \(x\),记录它最小的质因子的幂 记为 \(low[n]\) 比如 \(low[60]=2^{2}=4\)
若 \(x\) 的最小质因子 \(p\) 指数为一,那么直接套用公式 \(f(x)=f(\frac{x}{p}) \cdot f(p)\)
否则分两类讨论:
若 \(x=p^{k}\) 根据 \(f(p^{k-1})\) 计算 \(f(p^k)\)
否则把 \(x\) 分解成 \(\frac{x}{low[x]}\) 和 \(low[x]\) 再使用上面公式计算
example1:
筛 \(f(n)=\sum\limits_{d|n} d \cdot \varphi(d)\)
f[1] = 1;
for (int i = 2; i <= n; i++)
{
if (low[i] == 0)
{
low[i] = i, prime.emplace_back(i);
f[i] = 1ll * (i - 1) * i + 1ll;
}
for (auto j : prime)
{
if (i * j > n)
break;
if (i % j == 0)
{
low[i * j] = low[i] * j;
if (low[i] == i)
{
f[i * j] = f[i] + 1ll * (i * j - i) * (i * j);
}
else
{
f[i * j] = f[i / low[i]] * f[low[i] * j];
}
break;
}
low[i * j] = j;
f[i * j] = f[i] * f[j];
}
}
lazytag