您的位置:首页 > 其它

[BZOJ2693]jzptab(莫比乌斯反演)

2017-03-19 20:17 218 查看

题目描述

传送门

题解

刚开始感觉这题就是道水题啊,又一看模数tm不是质数啊

同样假设n<m

∑i=1n∑j=1m[i,j]

=∑i=1n∑j=1mij(i,j)

=∑i=1n∑j=1m∑d=1n[(i,j)=d]ijd

=∑d=1n∑i=1ndi∑j=1mdj[(i,j)=1]d

利用反演公式[n=1]=∑d|nμ(d)

=∑d=1n∑t=1nd∑i=1ndi[t|i]∑j=1mdj[t|j]μ(t)d

可以发现∑i=1ndi[t|i]实际上就是将[1..nd]中t的所有倍数都加起来,那么令s(n)=∑i=1ni=n(n+1)2,那么实际上∑i=1ndi[t|i]=s(ndt)t

于是原式

=∑d=1n∑t=1nds(ndt)s(mdt)t2μ(t)d

令T=dt,那么现在d为T的约数

=∑T=1ns(nT)s(mT)∑d|T(Td)2μ(Td)d

令F(n)=∑d|n(nd)2μ(nd)d,f(n)=n2μ(n),g(n)=n

这就是一个狄利克雷卷积的形式,F=f×g

可以发现f和g都是完全积性函数,那么F也是个积性函数

所以F可以根据莫比乌斯函数的性质用线性筛筛出来

显然当p为质数时,F(n)=−p2+p,当(a,b)=1时,F(a)=F(a)F(b)

那么需要注意的就是(a,b)≠1的情况,也就是如何用F(a)和p求出F(ap)

显然对于a=∏ipkii的某一个质因子pk来说,只有μ(1)和μ(p)是有价值的

F(pk)=f(1)pk+f(p)pk−1,F(pk+1)=f(1)pk+1+f(p)pk

也就是说每一项会多一个p

那么F(ap)=F(a)∗p

这样就能求出来F(n)了

回代原式

=∑T=1ns(nT)s(mT)F(T)

只有O(n−−√+m−−√)种取值

分块就可以了

时间复杂度O(n+T(n−−√+m−−√))

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define LL long long
#define N 10000005
#define Mod 100000009

int T,n,m,ans;
int p
,prime
;LL f
,s
;

void get(int n)
{
f[1]=1;s[1]=1;
for (int i=2;i<=n;++i)
{
if (!p[i])
{
prime[++prime[0]]=i;
f[i]=(i-(LL)i*i%Mod+Mod)%Mod;
}
s[i]=(LL)i*(i+1)/2%Mod;
for (int j=1;j<=prime[0]&&i*prime[j]<=n;++j)
{
p[i*prime[j]]=1;
if (i%prime[j]==0)
{
f[i*prime[j]]=f[i]*prime[j]%Mod;
break;
}
else f[i*prime[j]]=f[i]*f[prime[j]]%Mod;
}
}
for (int i=1;i<=n;++i) f[i]=(f[i]+f[i-1])%Mod;
}
int main()
{
get(10000000);
scanf("%d",&T);
while (T--)
{
scanf("%d%d",&n,&m);
if (n>m) swap(n,m);
ans=0;
for (int i=1,j=0;i<=n;i=j+1)
{
j=min(n/(n/i),m/(m/i));
ans+=s[n/i]*s[m/i]%Mod*(f[j]-f[i-1])%Mod;
ans=(ans%Mod+Mod)%Mod;
}
printf("%d\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: