题目描述
题解
刚开始感觉这题就是道水题啊,又一看模数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=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 和
所以
显然当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[N],prime[N];LL f[N],s[N];
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);
}
}