首页 > 代码库 > Bzoj3944 Sum

Bzoj3944 Sum

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 3673  Solved: 994

Description

技术分享

 

Input

一共T+1行
第1行为数据组数T(T<=10)
第2~T+1行每行一个非负整数N,代表一组询问
 

 

 

Output

一共T行,每行两个用空格分隔的数ans1,ans2
 

 

Sample Input

6
1
2
8
13
30
2333

Sample Output

1 1
2 0
22 -2
58 -3
278 -3
1655470 2

HINT

 

Source

 

数学问题 dirichlet卷积 莫比乌斯反演

目标函数: $ F(n)=\sum_{i=1}^{n} f(i) $

前缀和函数:$ G(n)=\sum_{i=1}^{n} g(i) $

卷积函数:$g(x)=f(i)*1=\sum_{i|x} f(i)$

用这些就可以搞事情了:

 

$ G(n)= \sum_{i=1}^{n} g(i)$

$=\sum_{i=1}^{n} \sum_{j|i} f(j) $

$=\sum_{j=1}^{n} \sum_{i=1}^{\lfloor \frac{n}{j} \rfloor} f(i) $

$=\sum_{j=1}^{n} F(\lfloor \frac{n}{j} \rfloor)$

我们要求的是$F(n)$,也就是$F(\lfloor \frac{n}{1} \rfloor)$

把原式移项得到$ F(n)=G(n)-\sum_{j=2}^{n} F(\lfloor \frac{n}{j} \rfloor) $

 

后面那些F可以分块递归算出。

 

求 $ \mu $ 的时候,那个卷积卷出来是e(第一项为1,后面为0),即$ G(n)=1 $

求 $ \varphi $的时候,那个卷积卷出来是id(第i项为i),即$G(n)=n*(n+1)/2$

预处理前500w项$ \varphi $ 和 $ \mu $ 的前缀和作为递归边界,就可以愉快地递归计算了。

 

若$G(n)$可以在$O(1)$时间内算出,则$F(n)$可以在$O(n^{\frac{3}{4}})$的时间内算出

如果预处理前$O(n^{\frac{2}{3}})$的部分,则$F(n)$可以在$O(n^{\frac{2}{3}})$的时间内算出

↑后面那一串F,分块计算的复杂度是 $ O(\sqrt{\frac{n}{k}}) $,递归下去用主定理之类的分析一波即可得出总复杂度(口胡,其实并没有尝试过)

 

 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 #include<map> 7 #define LL long long 8 using namespace std; 9 const int mxn=5000010;10 LL read(){11     LL x=0,f=1;char ch=getchar();12     while(ch<0 || ch>9){if(ch==-)f=-1;ch=getchar();}13     while(ch>=0 && ch<=9){x=x*10-0+ch;ch=getchar();}14     return x*f;15 }16 int pri[mxn],cnt=0;17 LL phi[mxn],mu[mxn];18 void init(){19     mu[1]=1;phi[1]=1;20     for(int i=2;i<mxn;i++){21         if(!phi[i]){22             pri[++cnt]=i; phi[i]=i-1; mu[i]=-1;23         }24         for(int j=1;j<=cnt && (LL)pri[j]*i<mxn;j++){25             int tmp=pri[j]*i;26             if(i%pri[j]==0){27                 mu[tmp]=0; phi[tmp]=phi[i]*pri[j]; break;28             }29             mu[tmp]=-mu[i];30             phi[tmp]=phi[i]*(pri[j]-1);31         }32     }33     for(int i=2;i<mxn;i++){34         phi[i]+=phi[i-1];35         mu[i]+=mu[i-1];36     }37     return;38 }39 int n;40 map<int,LL>mp,mump;41 LL calc_phi(LL x){42     if(x<mxn)return phi[x];43     if(mp.count(x))return mp[x];44     LL res=(LL)x*(x+1)>>1;45     for(LL i=2,pos;i<=x;i=pos+1){46         LL y=x/i;47         pos=x/y;48         res-=(pos-i+1)*calc_phi(y);49     }50     mp[x]=res;51     return res;52 }53 LL calc_mu(LL x){54     if(x<mxn)return mu[x];55     if(mump.count(x))return mump[x];56     LL res=1;57     for(LL i=2,pos;i<=x;i=pos+1){58         LL y=x/i;59         pos=x/y;60         res-=(pos-i+1)*calc_mu(y);61     }62     mump[x]=res;63     return res;64 }65 int main(){66     int i,j;67     init();68     int T=read();69     while(T--){70         n=read();71         LL ans1=calc_phi(n);72         LL ans2=calc_mu(n);73         printf("%lld %lld\n",ans1,ans2);74     }75     return 0;76 }

 

 

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 3673  Solved: 994
[Submit][Status][Discuss]

Description

技术分享

 

Input

一共T+1行
第1行为数据组数T(T<=10)
第2~T+1行每行一个非负整数N,代表一组询问
 

 

 

Output

一共T行,每行两个用空格分隔的数ans1,ans2
 

 

Sample Input

6
1
2
8
13
30
2333

Sample Output

1 1
2 0
22 -2
58 -3
278 -3
1655470 2

HINT

 

Source

Bzoj3944 Sum