●BZOJ 4176 Lucas的数论
Posted *ZJ
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了●BZOJ 4176 Lucas的数论相关的知识,希望对你有一定的参考价值。
题链:
http://www.lydsy.com/JudgeOnline/problem.php?id=4176
题解:
莫比乌斯反演,杜教筛
首先有这么一个结论:
令d(n)表示n的约数的个数(就是题目中的f(n)),则有
$$d(nm)=\\sum_{i|n}\\sum_{j|m}[gcd(i,j)==1]$$
●BZOJ 3994 [SDOI2015]约数个数和也用到了这个东西。
那么就下来接直接进行求ANS的式子的推导:
$$\\begin{aligned}
ANS&=\\sum_{n=1}^{N}\\sum_{m=1}^{N}d(nm)\\\\
&=\\sum_{n=1}^{N}\\sum_{m=1}^{N}\\sum_{i|n}\\sum_{j|m}[gcd(i,j)==1]\\\\
&=\\sum_{n=1}^{N}\\sum_{m=1}^{N}\\sum_{i|n}\\sum_{j|m}\\sum_{d|gcd(i,j)}\\mu(d)\\\\
&=\\sum_{d=1}^{N}\\mu(d)\\sum_{d|i}\\sum_{d|j}\\sum_{i|n,n\\leq N}\\sum_{j|m,m\\leq N} 1\\\\
&=\\sum_{d=1}^{N}\\mu(d)(\\sum_{d|i}\\lfloor \\frac{N}{i} \\rfloor)^2\\\\
&=\\sum_{d=1}^{N}\\mu(d)(\\sum_{i=1}^{\\lfloor \\frac{N}{d} \\rfloor}\\lfloor \\frac{N}{id} \\rfloor)^2\\end{aligned}$$
令$$f(n)=\\sum_{i=1}^{n}\\lfloor \\frac{n}{i} \\rfloor$$
则$$ANS=\\sum_{d=1}^{N}\\mu(d)f(\\lfloor \\frac{N}{d} \\rfloor)^2$$
这个求ANS的式子是可以分块+杜教筛(求每块$\\mu$的和)做的,
同时求f也可以分块求,
即这是一个块套块。。。
代码:
#include<bits/stdc++.h> #define DJM /*5623413*/ 1000000 using namespace std; const int mod=1000000007; struct Hash_Table{ #define Hmod 1425367 int org[DJM],val[DJM],nxt[DJM],head[Hmod],hnt; Hash_Table(){hnt=1;} void Push(int x,int v){ static int u; u=x%Hmod; org[hnt]=x; val[hnt]=v; nxt[hnt]=head[u]; head[u]=hnt++; } int Find(int x){ static int u; u=x%Hmod; for(int i=head[u];i;i=nxt[i]) if(org[i]==x) return val[i]; return -1; } }H; int pmu[DJM+50],mu[DJM+50]; void Sieve(){ static bool np[DJM+50]; static int prime[DJM+50],pnt; mu[1]=1; for(int i=2;i<=DJM;i++){ if(!np[i]) prime[++pnt]=i,mu[i]=-1; for(int j=1;j<=pnt&&i<=DJM/prime[j];j++){ np[i*prime[j]]=1; if(i%prime[j]) mu[i*prime[j]]=-mu[i]; else break; } } for(int i=1;i<=DJM;i++) pmu[i]=(1ll*mod+pmu[i-1]+mu[i])%mod; } int f(int n){ int ret=0; for(int i=1,last;i<=n;i=last+1){ last=n/(n/i); ret=(1ll*ret+1ll*(last-i+1)*(n/i))%mod; } return ret; } int DJ_pmu(int n){ if(n<=DJM) return pmu[n]; if(H.Find(n)!=-1) return H.Find(n); int ret=1; for(int i=2,last;i<=n;i=last+1){ last=n/(n/i); ret=(1ll*ret+mod-1ll*(last-i+1)*DJ_pmu(n/i)%mod)%mod; } H.Push(n,ret); return ret; } int main(){ Sieve(); int n,ans=0; scanf("%d",&n); for(int d=1,tmp,last;d<=n;d=last+1){ last=n/(n/d); tmp=f(n/d); tmp=1ll*tmp*tmp%mod; ans=(1ll*ans+(1ll*DJ_pmu(last)-DJ_pmu(d-1)+mod)%mod*tmp%mod)%mod; } printf("%d\\n",ans); return 0; }
以上是关于●BZOJ 4176 Lucas的数论的主要内容,如果未能解决你的问题,请参考以下文章