首页 > 代码库 > Bzoj4176 Lucas的数论
Bzoj4176 Lucas的数论
Description
去年的Lucas非常喜欢数论题,但是一年以后的Lucas却不那么喜欢了。
Input
第一行一个整数n。
Output
一行一个整数ans,表示答案模1000000007的值。
Sample Input
Sample Output
HINT
对于100%的数据n <= 10^9。
数学问题 莫比乌斯反演 脑洞题
$ans(n)=\sum_{i=1}^{n} \sum_{j=1}^{n} f(i,j)$
$=\sum_{i=1}^{n} \sum_{j=1}^{n} \sum_{k=1}^{n^2} [\frac{k}{gcd(i,j)}|j]$
(枚举gcd)
$=\sum_{d=1}^{n} d \sum_{i=1}^{\lfloor \frac{n}{d} \rfloor}\sum_{j=1}^{\lfloor \frac{n}{d} \rfloor}\sum_{k=1}^{\lfloor \frac{n^2}{d} \rfloor} [k|j][gcd(k,i)=1] $
(消掉j)
$=\sum_{d=1}^{n} d \sum_{i=1}^{\lfloor \frac{n}{d} \rfloor}\sum_{k=1}^{\lfloor \frac{n^2}{d} \rfloor} d \lfloor \frac{n}{dk} \rfloor [gcd(k,i)=1] $
(约掉一个d)
$=\sum_{d=1}^{n} \sum_{i=1}^{\lfloor \frac{n}{d} \rfloor}\sum_{k=1}^{\lfloor \frac{n^2}{d} \rfloor} \lfloor \frac{n}{k} \rfloor [gcd(k,i)=1] $
$=\sum_{d=1}^{n} \sum_{i=1}^{\lfloor \frac{n}{d} \rfloor}\sum_{k=1}^{\lfloor \frac{n^2}{d} \rfloor} \lfloor \frac{n}{k} \rfloor \sum_{t|(ik)} \mu(t)$
$= \sum_{t=1}^{1} \mu(t) \sum_{d=1}^{n} \sum_{i=1}^{\lfloor \frac{n}{dt} \rfloor}\sum_{k=1}^{\lfloor \frac{n^2}{dt} \rfloor} \lfloor \frac{n}{kt} \rfloor$
(注意到i对后面没有影响,把求和变为乘)
$= \sum_{t=1}^{1} \mu(t) \sum_{d=1}^{n} \lfloor \frac{n}{dt} \rfloor\sum_{k=1}^{\lfloor \frac{n^2}{dt} \rfloor} \lfloor \frac{n}{kt} \rfloor$
(注意到d在大于$ \lfloor \frac{n}{t} \rfloor$ 时,后面全是0,所以缩小求和上界,后面的k同理)
$= \sum_{t=1}^{1} \mu(t) \sum_{d=1}^{\lfloor \frac{n}{t} \rfloor} \lfloor \frac{n}{dt} \rfloor\sum_{k=1}^{\lfloor \frac{n}{t} \rfloor} \lfloor \frac{n}{kt} \rfloor$
$= \sum_{t=1}^{1} \mu(t) (\sum_{d=1}^{\lfloor \frac{n}{t} \rfloor} \lfloor \frac{n}{dt} \rfloor)^2 $
$\mu$的前缀和可以用bzoj3944的方法筛出来,后面的平方项可以分块计算。
也就是说分块套分块就可以愉快地出解了。
隔壁Sfailsth告诉我可以直接用Bzoj3994的结论来做
↓也就是从这个式子开始:
$\sum_{i=1}^{N}\sum_{j=1}^{M}d(ij)=\sum_{i=1}^{N}\sum_{j=1}^{M}\lfloor\frac{N}{i}\rfloor\lfloor\frac{M}{j}\rfloor\lbrack gcd(i,j)=1 \rbrack $
确实很方便
(做完这道题之后,陪伴了我们一年的权限号过期了)
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 mod=1e9+7;10 const int mxn=5000010;11 int read(){12 int x=0,f=1;char ch=getchar();13 while(ch<‘0‘ || ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}14 while(ch>=‘0‘ && ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}15 return x*f;16 }17 int pri[mxn],mu[mxn],cnt=0;18 bool vis[mxn];19 void init(){20 mu[1]=1;21 for(int i=2;i<mxn;i++){22 if(!vis[i]){23 pri[++cnt]=i;24 mu[i]=-1;25 }26 for(int j=1;j<=cnt && (LL)pri[j]*i<mxn;j++){27 int tmp=pri[j]*i;28 vis[tmp]=1;29 if(i%pri[j]==0){vis[tmp]=1;mu[tmp]=0;break;}30 mu[tmp]=-mu[i];31 }32 }33 for(int i=2;i<mxn;i++){mu[i]=mu[i-1]+mu[i];}34 return;35 }36 map<int,LL>mpmu;37 int F(int x){38 if(x<mxn)return mu[x];39 if(mpmu.count(x))return mpmu[x];40 int res=1;41 for(int i=2,pos;i<=x;i=pos+1){42 int y=x/i;43 pos=x/y;44 res=((LL)res-(LL)(pos-i+1)*F(y)%mod+mod)%mod;45 }46 mpmu[x]=res;47 return res;48 }49 int calc(int x){50 int res=0;51 for(int i=1,pos;i<=x;i=pos+1){52 int y=x/i;53 pos=x/y;54 res=(res+(pos-i+1)*(LL)y%mod)%mod;55 }56 return (LL)res*res%mod;57 }58 int main(){59 init();60 int n=read();61 LL ans=0;62 for(int i=1,pos;i<=n;i=pos+1){63 int y=n/i;pos=n/y;64 ans=((LL)ans+(((LL)F(pos)-F(i-1)%mod))*calc(y)%mod)%mod;65 }66 ans=(ans%mod+mod)%mod;67 printf("%lld\n",ans);68 return 0;69 }
Bzoj4176 Lucas的数论