杜教筛
我来填坑啦!(摘录自pengym大佬博客)
前置技能:
各种积性函数
- 我们平时所惯用的数论函数都是积性函数。
- 积性函数的定义:如果已知一个函数为数论函数,且,并且满足以下条件,若对于任意的两个互质的正整数都满足,那么称这个函数为积性函数。
- 特殊的,如果对于任意的正整数,也满足以上式子,则称这个函数为完全积性函数。
- 而本文的杜教筛,正是用来筛积性函数前缀和的一种神奇筛法!(当然比线性筛优秀啦)
常见积性函数
- μ–莫比乌斯函数。一会儿从另一种角度介绍它,顺便把上一节留的坑填一下。
- –欧拉函数。表示不大于n且与n互质的正整数个数。
- –约数个数。表示n的约数的个数。
- –约数和函数。即n的各个约数之和。表示为:。
(PS:接下来的是完全积性函数)
- –元函数。。
- –恒等函数。即对于所有的n,都为1。
- –单位函数。。
狄利克雷卷积(*)
基本知识
- 定义:两个数论函数和的卷积为。前面的括号代表将f卷g,后面的括号代表范围。
- 很显然,狄利克雷卷积满足以下运算规律:
- 交换律;
- 结合律;
- 分配律;
(PS:积性函数*积性函数仍然为积性函数!)
莫比乌斯函数μ
-
在上一节,我们了解了一个性质:
-
我们将这个性质转化为卷积的形式,即:。这在狄利克雷卷积中是一个很常用的恒等式。有了它,我们就可以补一下上一次的坑了!
-
证明莫比乌斯反演:
-
已知:
用狄利克雷卷积表示,即:。
我们知道与μ函数卷起来有特殊性质:
通过结合律:
代入后得:。
同理可以证明出另一种形式:。
-
欧拉函数 φ
-
φ。欧拉函数有一个性质,。
-
与上述方法类似,我们将它转化为狄利克雷卷积的形式:。
-
这时候有一个大胆的想法,两边同时卷上μ,会有什么发现呢?
-
来填第二个坑,欧拉函数与莫比乌斯函数的关系。
同时两边除以n,即:
。
杜教筛
-
我们现在需要计算:,为积性函数。
-
PS:接下来是杜教筛的套路式,latex打着太麻烦了,我就手写拍图好吧QAQ。
经过分析,只要当你的的前缀和很好求,能在较短时间内求出,那么我们对后面的式子进行整除分块,求S的复杂度为。
筛欧拉函数
筛莫比乌斯函数
Coding
#include<bits/stdc++.h>
#include<tr1/unordered_map>
#define ll long long
using namespace std;
const int N=5e6+10;
int t,n,cnt,p[N],v[N],mu[N],phi[N],sum1[N];
ll sum2[N];
tr1::unordered_map<int,int>w;
tr1::unordered_map<int,ll>w1;
void get(int maxn){
phi[1]=mu[1]=1;
for(int i=2;i<=maxn;++i){
if(!v[i]){
p[++cnt]=i;mu[i]=-1;phi[i]=i-1;
}
for(int j=1;j<=cnt;++j){
if(i*p[j]>maxn) break;
v[i*p[j]]=p[j];
if(i%p[j]==0){
phi[i*p[j]]=phi[i]*p[j];
break;
}
else mu[i*p[j]]=-mu[i],phi[i*p[j]]=phi[i]*(p[j]-1);
}
}
for(int i=1;i<=maxn;++i) sum1[i]=sum1[i-1]+mu[i],sum2[i]=sum2[i-1]+phi[i];
}
ll disphi(int N){
if(N<=5000000) return sum2[N];
if(w1[N]) return w1[N];
ll ans=1LL*(1+N)*N/2;
for(int l=2,r;l<=N;l=r+1){
r=N/(N/l);
ans-=1LL*disphi(N/l)*(r-l+1);
}
return w1[N]=ans;
}
int dismu(int N){
if(N<=5000000) return sum1[N];
if(w[N]) return w[N];
int ans=1;
for(int l=2,r;l>=0&&l<=N;l=r+1){
r=N/(N/l);
ans-=dismu(N/l)*(r-l+1);
}
return w[N]=ans;
}
int main(){
scanf("%d",&t);
get(5000000);
while(t--){
scanf("%d",&n);
printf("%lld %d\n",disphi(n),dismu(n));
}
return 0;
}