杜教筛
求积性函数前缀和
有一些重要且基本的积性函数:
\(\epsilon\), 满足
\[\epsilon(n) = [n = 1]
\]
\(1\), 满足
\[1(n) = 1
\]
\(id\), 满足
\[id(n) = n
\]
\[(f\ast g)(n) = \sum\limits_{d|n}f(d)g(\frac{n}{d})
\]
得到以下式子:
\[\mu\ast 1 = \epsilon
\]
\[\varphi\ast 1= id
\]
进入正题:
有积性函数\(f\),求\(f(1)+...+f(n)\)的和
令
\[S(i)=\sum_{i=1}^{n} f(i)
\]
要求的答案就是\(S(i)\)
先对于任意一个积性函数\(g\),求它与\(f\)卷积的和,
理解意义,\(f(d)g(\frac{i}{d})\) 即枚举 \(i\) ,算因数的贡献
\[\sum_{i=1}^{n}\sum_{d|i}f(d)g(\frac{i}{d})
\]
这里变换枚举顺序,乘积为 \(i\ast d (\leq n)\),即枚举因数,对乘积的贡献
\[=\sum_{i=1}^{n}\sum_{d=1}^{\lfloor \frac{n}{i} \rfloor}g(i)f(d)
\]
提出\(g(i)\)
\[=\sum_{i=1}^{n}g(i)\sum_{d=1}^{\lfloor \frac{n}{i} \rfloor}f(d)
\]
后面的和式替换成上面定义的\(S(i)\)
\[=\sum_{i=1}^{n}g(i)S(\lfloor \frac{n}{i} \rfloor)
\]
一开始的式子和解出的式子
\[\sum_{i=1}^{n}\sum_{d|i}f(d)g(\frac{i}{d}) = \sum_{i=1}^{n}g(i)S(\lfloor \frac{n}{i} \rfloor)
\]
分裂右边
\[\sum_{i=1}^{n}\sum_{d|i}f(d)g(\frac{i}{d}) = g(1)S(n) + \sum_{i=2}^{n}g(i)S(\lfloor \frac{n}{i} \rfloor)
\]
移项得
\[g(1)S(n) = \sum_{i=1}^{n}\sum_{d|i}f(d)g(\frac{i}{d}) - \sum_{i=2}^{n}g(i)S(\lfloor \frac{n}{i} \rfloor)
\]
右边\(S\)的取值有\(\lfloor \frac{n}{i} \rfloor\)种,用整除分块求出,时间\(O(\sqrt n)\)
\(\\\)
\(\\\)
求
\[\sum_{i = 1}^{n}\mu(i)
\]
把\(\mu\)当成\(f\),把\(1\)当成\(g\),代入上上面的式子中,即:
\[1(1)S(n) = \sum_{i=1}^{n}\sum_{d|i}\mu(d)1(\frac{i}{d}) - \sum_{i=2}^{n}1(i)S(\lfloor \frac{n}{i} \rfloor)
\]
开头有个式子:
因为
\[\mu\ast 1 = \epsilon
\]
即
\[\sum_{d|n}\mu(d)1(\frac{n}{d}) = \epsilon(n)
\]
所以
\[1(1)S(n) = \sum_{i=1}^{n}\epsilon(i) - \sum_{i=2}^{n}1(i)S(\lfloor \frac{n}{i} \rfloor)
\]
因为\(1,\epsilon\)的定义,可得
\[1 * S(n) = \sum_{i=1}^{n}[i = 1] - \sum_{i=2}^{n}1 * S(\lfloor \frac{n}{i} \rfloor)
\]
\[S(n) = 1 - \sum_{i=2}^{n}S(\lfloor \frac{n}{i} \rfloor)
\]
注意,这里的下标从\(2\)开始
\(\\\)
\(\\\)
求
\[\sum_{i=1}^{n} = \varphi(i)
\]
同上,\(\varphi\)代替\(f\),\(1\)代替\(g\)
得
\[1(1)S(n) = \sum_{i=1}^{n}\sum_{d|i}\varphi(d)1(\frac{i}{d}) - \sum_{i=2}^{n}1(i)S(\lfloor \frac{n}{i} \rfloor)
\]
因为
\[\varphi\ast 1= id
\]
得
\[1(1)S(n) = \sum_{i=1}^{n}id(i) - \sum_{i=2}^{n}1(i)S(\lfloor \frac{n}{i} \rfloor)
\]
即
\[S(n) = \sum_{i=1}^{n}id(i) - \sum_{i=2}^{n}S(\lfloor \frac{n}{i} \rfloor)
\]
由\(id(n) = n\)可得,
\[S(n) = \frac{(1+n)n}{2} - \sum_{i=2}^{n}S(\lfloor \frac{n}{i} \rfloor)
\]
LuoguP4213 【模板】杜教筛(Sum)
求\(\mu,\varphi\)的和的代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int T;
unordered_map<int, int> Mu;
unordered_map<int, ll> Phi;
//基于hash的map,查询期望O(1)
const int MAXN = 10000001;
int len;
int prime[2000000], mu[MAXN];
ll phi[MAXN];
bool isprime[MAXN];
//线性筛预处理1~10^7的phi,mu的和
void pre(){
int N = MAXN;
// memset(isprime, 1, sizeof(isprime));卡卡常
mu[1] = 1;
phi[1] = 1;
for(int i = 2; i <= N; i++){
if (!isprime[i]){
prime[++len] = i;
mu[i] = - 1;
phi[i] = i - 1;
}
for(int j = 1; j <= len && prime[j] * i <= N; j++){
int k = prime[j] * i;
isprime[k] = true;
if (i % prime[j] == 0) {
phi[k] = phi[i] * prime[j];
//这里可以这样转移,比较特殊,其他的就不一定了
break;
}
phi[k] = phi[prime[j]] * phi[i];
mu[k] = -mu[i];
}
}
for(int i = 1; i <= N; i++)
mu[i] += mu[i - 1],
phi[i] += phi[i - 1];
}
//递归求解
int MuSum(int n){
if (n <= MAXN) return mu[n];
if (Mu.count(n)) return Mu[n];
//预处理减少时间
int sum = 0, r;
for(int l = 2; l <= n; l = r + 1){
r = n/(n/l);
sum += MuSum(n/l) * (r - l + 1);
}
sum = 1 - sum;
Mu[n] = sum;
return sum;
}
ll PhiSum(int n){
if (n <= MAXN) return phi[n];
if (Phi.count(n)) return Phi[n];
ll sum = 0, r;
for(int l = 2; l <= n; l = r + 1){
r = n/(n/l);
sum += PhiSum(n/l) * (r - l + 1);
}
sum = 1ll*(1+n)*n/2 - sum;
Phi[n] = sum;
return sum;
}
int main(){
pre();
scanf("%d", &T);
while(T--){
int n;
scanf("%d", &n);
ll ans1 = PhiSum(n);int ans2 = MuSum(n);
printf("%lld %d\n",ans1,ans2);
}
return 0;
}