杜教筛 && bzoj3944 Sum
Description
Input
Output
Sample Input
1
2
8
13
30
2333
Sample Output
1 1
2 0
22 -2
58 -3
278 -3
1655470 2
正解:线性筛+杜教筛。
杜教筛板子题。然而感觉自己还不是很理解的样子。。
唐老师博客:http://blog.csdn.net/skywalkert/article/details/50500009
xLightGod博客:http://blog.xlightgod.com/dirichlet%E5%8D%B7%E7%A7%AF%E4%B8%8E%E6%9D%9C%E6%95%99%E7%AD%9B/
杜教筛可以在低于线性复杂度的时间内求出一些积性函数的前缀和。
为了更快地求$F(i)=\sum_{i=1}^{n}f(i)$,我们构造一个函数$g(n)$,求出$(f*g)(n)$的前缀和。
$\sum_{i=1}^{n}(f*g)(i)=\sum_{i=1}^{n}\sum_{d|i}f(d)g(\frac{i}{d})=\sum_{ij<=n}f(i)g(j)=\sum_{i=1}^{n}g(i)F(\left \lfloor \frac{n}{i} \right \rfloor)$
所以$g(1)F(n)=\sum_{i=1}^{n}(f*g)(i)-\sum_{i=2}^{n}g(i)F(\left \lfloor \frac{n}{i} \right \rfloor)$
于是我们的目标就是快速求出$\sum_{i=1}^{n}(f*g)(i)$和$g(i)$的前缀和。这样我们的复杂度就是$O(n^{\frac{3}{4}})$,如果我们将$O(n^{\frac{2}{3}})$以内的$F(i)$预处理,那么复杂度就可以降到$O(n^{\frac{2}{3}})$(复杂度怎么证。。)
$g$一般取恒等函数$I$。
所以求$\sum_{i=1}^{n}\mu(i)$,那就是求$\sum_{i=1}^{n}\sum_{d|i}\mu(d)-\sum_{i=2}^{n}F(\left \lfloor \frac{n}{i} \right \rfloor)$
则$Ans=1-\sum_{i=2}^{n}F(\left \lfloor \frac{n}{i} \right \rfloor)$
求$\sum_{i=1}^{n}\phi(i)$,那就是求$\sum_{i=1}^{n}\sum_{d|i}\phi(d)-\sum_{i=2}^{n}F(\left \lfloor \frac{n}{i} \right \rfloor)$
则$Ans=\frac{n(n+1)}{2}-\sum_{i=2}^{n}F(\left \lfloor \frac{n}{i} \right \rfloor)$
于是$Ans$的后面那一坨我们用记忆化搜索,空间开不了??我是用的map。开始先把2500000以内的答案线性筛预处理出来,然后搜索即可。(为什么是2500000,因为我发现这样快一些。。复杂度太玄学了。。)
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <complex> 5 #include <cstring> 6 #include <cstdlib> 7 #include <cstdio> 8 #include <vector> 9 #include <cmath> 10 #include <queue> 11 #include <stack> 12 #include <map> 13 #include <set> 14 #define inf (1<<30) 15 #define N (2500010) 16 #define il inline 17 #define RG register 18 #define ll long long 19 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 20 21 using namespace std; 22 23 struct node{ ll phi,mu; }ans; 24 25 map <ll,ll> Phi,Mu; 26 ll vis[N],phi[N],mu[N],prime[N],n,cnt; 27 28 il ll gi(){ 29 RG ll x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 30 if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x; 31 } 32 33 il void sieve(){ 34 vis[1]=phi[1]=mu[1]=1; 35 for (RG ll i=2;i<N;++i){ 36 if (!vis[i]) phi[i]=i-1,mu[i]=-1,prime[++cnt]=i; 37 for (RG ll j=1,k=i*prime[j];j<=cnt && k<N;++j,k=i*prime[j]){ 38 vis[k]=1; 39 if (i%prime[j]) phi[k]=phi[i]*phi[prime[j]],mu[k]=-mu[i]; 40 else{ phi[k]=phi[i]*prime[j]; break; } 41 } 42 } 43 for (RG ll i=2;i<N;++i) phi[i]+=phi[i-1],mu[i]+=mu[i-1]; return; 44 } 45 46 il node du(RG ll n){ 47 if (n<N) return (node){phi[n],mu[n]}; 48 if (Phi[n]) return (node){Phi[n],Mu[n]}; 49 RG ll ans1=n*(n+1)>>1,ans2=1,pos=0; RG node res; 50 for (RG ll i=2;i<=n;i=pos+1){ 51 pos=n/(n/i),res=du(n/i); 52 ans1-=(pos-i+1)*res.phi; 53 ans2-=(pos-i+1)*res.mu; 54 } 55 Phi[n]=ans1,Mu[n]=ans2; 56 return (node){ans1,ans2}; 57 } 58 59 il void work(){ 60 n=gi(); ans=du(n); 61 printf("%lld %lld\n",ans.phi,ans.mu); 62 return; 63 } 64 65 int main(){ 66 File("du"); 67 sieve(); RG ll T=gi(); 68 while (T--) work(); 69 return 0; 70 }