题解
数论劝退…真的对第一次学的我太不友好了…
请务必看一下大佬的博客
首先,看到 ∑ d ∣ n f ( d ) \sum_{d|n}f(d) ∑d∣nf(d) 要能想到莫比乌斯反演,
在莫比乌斯反演里有这么一个定理:
如果 F(n) 和 f(n) 满足
F
(
n
)
=
∑
d
∣
n
f
(
d
)
F(n)=\sum_{d|n}f(d)
F(n)=∑d∣nf(d),
那么
f
(
n
)
=
∑
d
∣
n
μ
(
d
)
F
(
⌊
n
d
⌋
)
f(n)=\sum_{d|n}μ(d)F(⌊\frac{n}{d}⌋)
f(n)=∑d∣nμ(d)F(⌊dn⌋),
即
f
=
F
∗
μ
f=F*μ
f=F∗μ,
其中
μ
μ
μ是莫比乌斯函数,是个积性函数哦
是不是和题目中的 ∑ i = 1 n f ( i ) \sum^{n}_{i=1}f(i) ∑i=1nf(i) 联系起来了?
顺便改写一下题目, F ( n ) = n 2 − 3 n + 2 F(n)=n^2-3n+2 F(n)=n2−3n+2
我们知道杜教筛是用来求积性函数的前缀和的,
那就直接让
S
(
n
)
=
∑
i
=
1
n
f
(
i
)
S(n)=\sum^{n}_{i=1}f(i)
S(n)=∑i=1nf(i) 吧!
然后,我们套用杜教筛常用公式
g
(
1
)
S
(
n
)
=
∑
i
=
1
n
(
f
∗
g
)
(
i
)
−
∑
d
=
2
n
g
(
d
)
S
(
⌊
n
d
⌋
)
g(1)S(n)=\sum^{n}_{i=1}(f*g)(i)-\sum^{n}_{d=2}g(d)S(⌊\frac{n}{d}⌋)
g(1)S(n)=∑i=1n(f∗g)(i)−∑d=2ng(d)S(⌊dn⌋),
这里的
g
g
g 选用恒等函数
I
(
n
)
I(n)
I(n),对就是那个值恒等于1的积性函数,
然后改写一下公式:
I
(
1
)
⋅
S
(
n
)
=
∑
i
=
1
n
(
f
∗
I
)
(
i
)
−
∑
d
=
2
n
I
(
d
)
⋅
S
(
⌊
n
d
⌋
)
I(1)·S(n)=\sum^{n}_{i=1}(f*I)(i)-\sum^{n}_{d=2}I(d)·S(⌊\frac{n}{d}⌋)
I(1)⋅S(n)=∑i=1n(f∗I)(i)−∑d=2nI(d)⋅S(⌊dn⌋),
注意区分一下 ·
是数值上的乘法,*
是卷积,之前就这里把自己绕晕了
还记得之前说的
f
=
F
∗
μ
f=F*μ
f=F∗μ 吗?
再改一下,
S
(
n
)
=
∑
i
=
1
n
(
F
∗
μ
∗
I
)
(
i
)
−
∑
d
=
2
n
S
(
⌊
n
d
⌋
)
S(n)=\sum^{n}_{i=1}(F*μ*I)(i)-\sum^{n}_{d=2}S(⌊\frac{n}{d}⌋)
S(n)=∑i=1n(F∗μ∗I)(i)−∑d=2nS(⌊dn⌋)
学习大佬博客后知道
μ
∗
I
=
ϵ
μ*I=ϵ
μ∗I=ϵ,那个表示单位的元函数
(也就是说
I
I
I 是
μ
μ
μ 的逆元)
最后式子变成, S ( n ) = ∑ i = 1 n F ( i ) − ∑ d = 2 n I ( d ) ⋅ S ( ⌊ n d ⌋ ) S(n)=\sum^{n}_{i=1}F(i)-\sum^{n}_{d=2}I(d)·S(⌊\frac{n}{d}⌋) S(n)=∑i=1nF(i)−∑d=2nI(d)⋅S(⌊dn⌋)
结合题目,
S
(
n
)
=
∑
i
=
1
n
(
i
2
−
3
i
+
2
)
−
∑
d
=
2
n
I
(
d
)
⋅
S
(
⌊
n
d
⌋
)
S(n)=\sum^{n}_{i=1}(i^2-3i+2)-\sum^{n}_{d=2}I(d)·S(⌊\frac{n}{d}⌋)
S(n)=∑i=1n(i2−3i+2)−∑d=2nI(d)⋅S(⌊dn⌋)
其中 ∑ i = 1 n ( i 2 − 3 i + 2 ) = n ( n + 1 ) ( n + 2 ) 6 − 3 ∗ n ( n + 1 ) 2 + 2 n = n ( n − 1 ) ( n − 2 ) 3 \sum^{n}_{i=1}(i^2-3i+2)=\cfrac{n(n+1)(n+2)}{6}-3*\cfrac{n(n+1)}{2}+2n=\cfrac{n(n-1)(n-2)}{3} ∑i=1n(i2−3i+2)=6n(n+1)(n+2)−3∗2n(n+1)+2n=3n(n−1)(n−2)
最终,
S
(
n
)
=
n
(
n
−
1
)
(
n
−
2
)
3
−
∑
d
=
2
n
I
(
d
)
⋅
S
(
⌊
n
d
⌋
)
S(n)=\frac{n(n-1)(n-2)}{3}-\sum^{n}_{d=2}I(d)·S(⌊\frac{n}{d}⌋)
S(n)=3n(n−1)(n−2)−∑d=2nI(d)⋅S(⌊dn⌋)
我终于会了!!!
#include <bits/stdc++.h>
#include <tr1/unordered_map>//unordered_map所在的头文件
using namespace std;
typedef long long ll;
const int N=1e6+10;
const int mod=1e9+7;
int m;
unordered_map<int,ll>S;//n高达1e9 需要unordered_map存答案记忆化
ll inv3;
ll F(int n){return 1ll*n*n-1ll*3*n+2;}
ll qpow(ll a,ll b){
ll res=1;
while(b){
if(b&1)res=res*a%mod;
b>>=1;
a=a*a%mod;
}
return res;
}
ll sum_f[N];
ll get_S(int n){
if(n<=m) return sum_f[n];//如果n的范围小于根号(最大范围) 直接返回提前预处理好的前缀和
if(S[n]) return S[n];//记忆化
ll res=1ll*n*(n-1)%mod*(n-2)%mod*inv3%mod;//F前缀和
for (int l = 2,r; l <=n ; l=r+1) {
r=n/(n/l);
res-=(r-l+1)*get_S(n/l)%mod;
//I(d)在[l,r]的和
res=(res+mod)%mod;//有负数的风险
}
return S[n]=res;
}
int n,k;
int mu[N],prime[N],tot=0;
bool vis[N];
void get_mu(){//筛选莫比乌斯函数
mu[1]=1;
for (int i = 2; i < N; ++i) {
if(!vis[i]){
prime[++tot]=i;
mu[i]=-1;
}
for (int j = 1; j <= tot && i*prime[j]<N; ++j) {
vis[i*prime[j]]=true;
if(i%prime[j]==0){
mu[i*prime[j]]=0;//里面肯定有两个prime[j]
break;
}else{
mu[i*prime[j]]=-mu[i];//多了个质数
}
}
}
}
void init(){
m=(int)sqrt(1e9);//sqrt(1e9)
inv3=qpow(3,mod-2);
get_mu();
for (int i = 1; i <= m; ++i) {//统计每个f[n] 就是反演那个推论
for (int j = i; j <= m; j+=i) {
sum_f[j]+=1ll*mu[i]*F(j/i);
sum_f[j]%=mod;
}
}
for (int i = 1; i <= m; ++i) {//小范围统计S[n]
sum_f[i]=sum_f[i]+sum_f[i-1];
sum_f[i]%=mod;
}
}
int main(){
ios::sync_with_stdio(0);
init();//不预处理必T
int T;
cin>>T;
for (int cs = 1; cs <= T; ++cs) {
cin>>n;
cout <<get_S(n) << endl;
}
return 0;
}