【bzoj 4176】 Lucas的數論 莫比烏斯反演(杜教篩)
Description
去年的Lucas非常喜歡數論題,但是一年以後的Lucas卻不那麽喜歡了。
在整理以前的試題時,發現了這樣一道題目“求Sigma(f(i)),其中1<=i<=N”,其中 表示i的約數個數。他現在長大了,題目也變難了。
求如下表達式的值:
一行一個整數ans,表示答案模1000000007的值。
Sample Input
2
Sample Output
8
HINT
對於100%的數據n <= 10^9。
題解:
解鎖新技能:杜教篩。
再復習一下:
若$F(n)=\sum_{i=1}^{n}f(i),g(i)=\sum_{j|i}f(i),G(n)=\sum_{i=1}^{n}g(i)$,
則有:$G(n)=\sum_{i=1}^{n}F(\lfloor\frac{n}{i}\rfloor)$。
即:$F(n)=G(n)-\sum_{i=2}^{n}F(\lfloor\frac{n}{i}\rfloor)$
然後就可以上杜教篩了。
話歸正題:
對於本題,其實和bzoj3994式子一樣……
$\sum_{i=1}^{n}\sum_{j=1}^{n}f(ij)$
$=\sum_{i=1}^{n}\sum_{j=1}^{n}\sum_{p=1}^{n^{2}}[p|ij]$
$=\sum_{i=1}^{n}\sum_{j=1}^{n}\sum_{p=1}^{n^{2}}[\frac{p}{(p,i)}|j]$
$=\sum_{t=1}^{n}\sum_{i=1}^{\lfloor\frac{n}{t}\rfloor}\sum_{j=1}^{n}\sum_{p=1}^{\lfloor\frac{n^{2}}{t}\rfloor}[p|j]*[(i,p)==0]$
$=\sum_{t=1}^{n}\sum_{i=1}^{\lfloor\frac{n}{t}\rfloor}\sum_{p=1}^{\lfloor\frac{n^{2}}{t}\rfloor}\sum_{d|(i,j)}\mu(d)\lfloor \frac{n}{p} \rfloor$
$=\sum_{d=1}^{n}\mu(d)\sum_{t=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{i=1}^{\lfloor\frac{n}{td}\rfloor}\sum_{p=1}^{\lfloor\frac{n^{2}}{td}\rfloor}\lfloor\frac{n}{pd}\rfloor$
$n>=pd,n^{2}>=tdn$
$\therefore Ans=\sum_{d=1}^{n}\mu(d)\sum_{t=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{i=1}^{\lfloor\frac{n}{td}\rfloor}\sum_{p=1}^{\lfloor\frac{n}{td}\rfloor}\lfloor\frac{n}{pd}\rfloor$
$Ans=\sum_{d=1}^{n}\mu(d)\sum_{t=1}^{\lfloor\frac{n}{d}\rfloor}\lfloor\frac{n}{td}\rfloor\sum_{p=1}^{\lfloor\frac{n}{d}\rfloor}\lfloor\frac{n}{pd}\rfloor$
$設f(i)=\sum_{x=1}^{i}\lfloor\frac{i}{x} \rfloor$
$\therefore Ans=\sum_{d=1}^{n}\mu(d)f(\lfloor\frac{n}{d}\rfloor)$
然後分塊+杜教篩即可。
代碼:
1 #include<cstdio>
2 using namespace std;
3 typedef long long ll;
4 const ll N=(ll)3e6+1;
5 const ll mod=1000000007ll;
6 short miu[N];
7 int prim[N/10],num;
8 bool vis[N];
9 int sum[N];
10 inline void init(){
11 miu[1]=sum[1]=1;
12 for(int i=2;i<N;i++){
13 if(!vis[i]){
14 prim[++num]=i;
15 miu[i]=-1;
16 }for(int j=1;j<=num&&prim[j]*i<N;j++){
17 vis[i*prim[j]]=1;
18 if(i%prim[j]==0){
19 miu[i*prim[j]]=0;
20 break;
21 }
22 else
23 miu[i*prim[j]]=-miu[i];
24 }
25 // printf("miu[%d]=%d\n",i,miu[i]);
26 }
27 for(int i=2;i<N;i++)
28 sum[i]=sum[i-1]+miu[i];
29 }
30 struct edges{
31 ll v;int w;edges *last;
32 }edge[N/10],*head[76545];int cnt;
33 const int limit=76543;
34 inline void push(int u,ll v,int w){
35 edge[++cnt]=(edges){v,w,head[u]};head[u]=edge+cnt;
36 }
37 inline ll Get_sum(ll x){
38 if(x<N) return sum[x];
39 int t=x%limit;
40 for(edges *i=head[t];i;i=i->last)
41 if(i->v==x) return i->w;
42 ll ans=1;
43 for(ll i=2,pos;i<=x;i=pos+1){
44 pos=x/i;
45 pos=x/pos;
46 ans-=(pos-i+1)*Get_sum(x/pos);
47 }
48 push(t,x,ans);
49 return ans;
50 }
51 inline ll Get_F(ll x){
52 ll ans=0;
53 for(ll i=1,pos;i<=x;i=pos+1){
54 pos=x/i;
55 pos=x/pos;
56 ll t=x/i;
57 ans+=t*(pos-i+1);
58 ans%=mod;
59 }return ans;
60 }
61 inline ll solve(ll x){
62 ll ans=0;
63 for(ll i=1,pos;i<=x;i=pos+1){
64 pos=x/i;
65 pos=x/pos;
66 ll t=Get_F(x/i);
67 ans+=(Get_sum(pos)-Get_sum(i-1))%mod*t%mod*t%mod;
68 ans%=mod;
69 }
70 return (ans%mod+mod)%mod;
71 }
72 int main(){
73 init();
74 ll a;
75 scanf("%lld",&a);
76 printf("%lld\n",solve(a));
77 }
【bzoj 4176】 Lucas的數論 莫比烏斯反演(杜教篩)