一般求法:
求 ∑ i = 1 n f ( x ) \sum_{i=1}^{n}{f(x)} ∑i=1nf(x)
找出两个积性函数 h ( x ) h(x) h(x)和 g ( x ) g(x) g(x),满足 g ( x ) = h ( x ) ∗ f ( x ) g(x)=h(x)*f(x) g(x)=h(x)∗f(x),(*表示卷积)
然后有 ∑ i = 1 n g ( x ) = ∑ i = 1 n ∑ d ∣ i h ( d ) ⋅ f ( n d ) \sum_{i=1}^{n}g(x)=\sum_{i=1}^{n}\sum_{d|i}h(d)\cdot f(\frac{n}{d}) ∑i=1ng(x)=∑i=1n∑d∣ih(d)⋅f(dn)
∑ i = 1 n g ( x ) = ∑ d = 1 n h ( d ) ⋅ ∑ j = 1 ⌊ n d ⌋ f ( j ) \sum_{i=1}^{n}g(x)=\sum_{d=1}^{n}h(d)\cdot\sum_{j=1}^{\lfloor\frac{n}{d}\rfloor}f({j}) ∑i=1ng(x)=∑d=1nh(d)⋅∑j=1⌊dn⌋f(j)
记 s ( x ) = ∑ i = 1 x f ( x ) s(x)=\sum_{i=1}^{x}f(x) s(x)=∑i=1xf(x)
∑ i = 1 n g ( x ) = ∑ d = 1 n h ( d ) ⋅ s ( ⌊ n d ⌋ ) ) \sum_{i=1}^{n}g(x)=\sum_{d=1}^{n}h(d)\cdot s(\lfloor\frac{n}{d}\rfloor)) ∑i=1ng(x)=∑d=1nh(d)⋅s(⌊dn⌋))
右边提取第一项 h ( 1 ) ∗ s ( 1 ) h(1)*s(1) h(1)∗s(1),把剩余的移到左边等式变为:
h ( 1 ) ∗ s ( n ) = ∑ i = 1 n g ( x ) − ∑ d = 2 n h ( d ) ⋅ s ( ⌊ n d ⌋ ) ) h(1)*s(n) =\sum_{i=1}^{n}g(x) -\sum_{d=2}^{n}h(d)\cdot s(\lfloor\frac{n}{d}\rfloor)) h(1)∗s(n)=∑i=1ng(x)−∑d=2nh(d)⋅s(⌊dn⌋))
通常
∑
i
=
1
n
g
(
x
)
\sum_{i=1}^{n}g(x)
∑i=1ng(x)和
h
(
1
)
h(1)
h(1)很容易快速得到,所以只要解决
∑
d
=
2
n
h
(
d
)
⋅
s
(
⌊
n
d
⌋
)
)
\sum_{d=2}^{n}h(d)\cdot s(\lfloor\frac{n}{d}\rfloor))
∑d=2nh(d)⋅s(⌊dn⌋))这部分就可以得到
s
(
n
)
s(n)
s(n)
这部分可以使用分块快速得到
一般是先对可打表的范围预处理,然后求解的时候如果n较小,直接输出答案即可;n较大时采用递归求解的方式来解决。需要保存那些不在打表范围的结果,也就是记忆化。
模板题中:
求
∑
i
=
1
n
ϕ
(
i
)
\sum_{i=1}^{n}\phi(i)
∑i=1nϕ(i)
容易想到
ϕ
∗
I
=
i
d
\phi*I=id
ϕ∗I=id,其中
I
(
x
)
=
1
,
i
d
(
x
)
=
x
I(x)=1,id(x)=x
I(x)=1,id(x)=x
求
∑
i
=
1
n
μ
(
i
)
\sum_{i=1}^{n}\mu(i)
∑i=1nμ(i)
容易想到
μ
∗
I
=
e
\mu*I=e
μ∗I=e,其中
I
(
x
)
=
1
,
e
(
x
)
=
(
x
=
1
?
1
:
0
)
I(x)=1,e(x)=(x=1?1:0)
I(x)=1,e(x)=(x=1?1:0)
后面照着过程一步一步下来很容易可以解出
常用数论函数:
函数 | |
---|---|
d ( n ) = ∑ d ∥ n 1 d(n)=\sum_{d\|n}1 d(n)=∑d∥n1 | 因数个数 |
σ ( n ) = ∑ d ∥ n d \sigma(n)=\sum_{d\|n}d σ(n)=∑d∥nd | 因数和 |
e ( n ) = n = = 1 ? 1 : 0 e(n)=n==1?1:0 e(n)=n==1?1:0 | 幺元函数 |
I ( n ) = 1 I(n)=1 I(n)=1 | 恒等函数 |
ϕ ( n ) \phi(n) ϕ(n) | 欧拉函数 |
μ ( n ) \mu(n) μ(n) | 莫比乌斯函数 |
i d ( n ) = n id(n)=n id(n)=n | 单位函数 |
i d k ( n ) = n k idk(n)=n^{k} idk(n)=nk | 幂函数 |
μ
∗
1
=
ϵ
\mu * 1=\epsilon
μ∗1=ϵ
ϕ
∗
1
=
I
d
\phi * 1=Id
ϕ∗1=Id
ϕ
=
I
d
∗
μ
\phi = Id * \mu
ϕ=Id∗μ
d
=
1
∗
1
d=1∗1
d=1∗1
1
=
μ
∗
d
1 = \mu * d
1=μ∗d
参考:
#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
typedef long long ll;
const int N=5e6+5;
const int M=5e6;
int mu[N];
ll phi[N];
bool vis[N];
int prime[N],tot;
void work_pre(int maxn)
{
phi[1]=mu[1]=1;
for(int i=2;i<=maxn;i++)
{
if(!vis[i])
{
prime[++tot]=i;
mu[i]=-1;phi[i]=i-1;
}
for(int j=1;j<=tot&&prime[j]*i<=maxn;j++)
{
vis[i*prime[j]]=1;
if(i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
else mu[i*prime[j]]=-mu[i],phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
for(int i=1;i<=maxn;i++){
phi[i]+=phi[i-1];
mu[i]+=mu[i-1];
}
}
unordered_map<int,int>mp1;
unordered_map<int,ll>mp2;
int djs_mu(int n){
if(n<=M){
return mu[n];
}
if(mp1[n]){
return mp1[n];
}
int ret=1;
for(int l=2,r;n>=l;l=r+1){
r=n/(n/l);
ret-=(r-l+1)*djs_mu(n/l);
}
return mp1[n]=ret;
}
ll djs_phi(int n){
if(n<=M){
return phi[n];
}
if(mp2[n]){
return mp2[n];
}
ll ret=1ll*n*(n+1)/2;
for(int l=2,r;n>=l;l=r+1){
r=n/(n/l);
ret-=1ll*(r-l+1)*djs_phi(n/l);
}
return mp2[n]=ret;
}
int main(){
work_pre(M);
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++){
int n;
scanf("%d",&n);
printf("%lld %d\n",djs_phi(n),djs_mu(n));
}
return 0;
}