1. 程式人生 > >【bzoj 4176】 Lucas的數論 莫比烏斯反演(杜教篩)

【bzoj 4176】 Lucas的數論 莫比烏斯反演(杜教篩)

amp short last ++ esc output sig blog tro


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的數論 莫比烏斯反演(杜教篩)