亚线性筛之一
杜教筛
前置知识
积性函数
前言
首先先看一下积性函数吧,积性函数就是在对于所有的互质的 a 和 b ,总有 f(ab)=f(a)f(b) , 则 f(x) 为积性函数。
比较常见的主要有:
d(x)=i∣n∑1σ(x)=i∣n∑iφ(x)=i=1∑x1[gcd(x,i)=1]μ(x)=⎩⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎧1(−1)k0x=1i=1∏kqi=1max{qi}>1ϵ(x)=[x=1]
积性函数有以下性质:
若 f(x),g(x)为积性函数,则,
h(x)=f(xp)h(x)=fp(x)h(x)=f(x)g(x)h(x)=d∣x∑f(d)g(dx)
中的h(x)也为积性函数。
杜教筛主要是用来求像这些积性函数的前缀和。
正文
对于求一个数论函数的前缀和,杜教筛可以在低于线性时间的复杂度内求解。
对于数论函数 f , 要求计算 S(n)=∑i=1nf(i) 。
首先构造一个 S(n) 关于S(⌊in⌋) 的递推式
对于任意一个数论函数 g ,必须满足
i=1∑nd∣i∑g(d)f(di)=i=1∑ng(i)S(⌊in⌋)⟺i=1∑n(f∗g)(i)=i=1∑ng(i)S(⌊in⌋)
简单的证明:
i=1∑nd∣i∑g(d)f(di)=i=1∑nj=1∑⌊in⌋g(i)f(j)=i=1∑ng(i)j=1∑⌊in⌋f(j)=i=1∑ng(i)S(⌊in⌋)
求出递推式
g(1)S(n)=i=1∑n(f∗g)(i)−i=2∑ng(i)S(⌊in⌋)
可以用数论分块对后半部分快速求出结果。
问题
S1(n)=i=1∑nμ(i)S2(n)=i=1∑nφ(i)
第一部分求莫比乌斯函数前缀和
∵ϵ=μ∗1∴ϵ=d∣n∑μ(d)S1(n)=i=1∑nϵ(i)−i=2∑nS1(⌊in⌋)=1−i=2∑nS1(⌊in⌋)
直接整除分块
第二部分求欧拉函数前缀和
∵φ∗1=ID∴i=1∑n(φ∗1)(i)=i=1∑n1⋅S2(⌊in⌋)i=1∑nID(i)=i=1∑n1⋅S2(⌊in⌋)21n(n+1)=i=1∑nS2(⌊in⌋)S2(n)=21n(n+1)−i=2∑nS2(⌊in⌋)
时间复杂度O(n32)
code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| #include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=2e6+10; int T,cnt,n; ll mu[maxn],prime[maxn],S1[maxn],S2[maxn]; bool vis[maxn]; map<ll,ll> eit; void Mu() { mu[1]=1; for(int i=2;i<=2e6;i++) { if(!vis[i]) { prime[++cnt]=i; mu[i]=-1; } for(int j=1;j<=cnt&&prime[j]*i<=2e6;j++) { vis[prime[j]*i]=true; if(i%prime[j]==0) { mu[prime[j]*i]=0; break; } mu[prime[j]*i]=-mu[i]; } } for(int i=1;i<=2e6;i++) S1[i]=S1[i-1]+mu[i]; } ll S_mu(ll x) { if(x<=2e6)return S1[x]; if(eit[x])return eit[x]; ll res=1; for(ll l=2,r;l<=x;l=r+1) { r=x/(x/l); res-=S_mu(x/l)*(r-l+1); } return eit[x]=res; } ll S_phi(ll x) { ll res=0; for(ll l=1,r;l<=x;l=r+1) { r=x/(x/l); res+=(S_mu(r)-S_mu(l-1))*(x/l)*(x/l); } return (res-1)/2+1; } int main() { Mu(); scanf("%d",&T); while(T--) { scanf("%lld",&n); printf("%lld %lld\n",S_phi(n),S_mu(n)); } return 0; }
|
对于一些筛法的小技巧:
对于比较大的数据时,筛法在筛前半段时花费的时间显然是比较长的,这时我们可以直接线性筛一遍先记录下来,在求后半段时就可以省下大部分时间,称为根号分治。