题目描述
题解
感觉这题非常强
假设
n<m
∑i=1n∑j=1m(i,j)k
=∑i=1n∑j=1m∑d=1n[(i,j)=d]dk
=∑d=1ndk∑i=1nd∑j=1md[(i,j)=1]
用一下反演公式 [n=1]=∑d|nμ(d)
=∑d=1ndk∑i=1nd∑j=1md∑t|(i,j)μ(t)
=∑d=1ndk∑t=1nd∑i=1nd[t|i]∑j=1md[t|j]μ(t)
=∑d=1ndk∑t=1nd⌊ndt⌋⌊mdt⌋μ(t)
令 T=dt ,此时 d 为
=∑T=1n⌊nT⌋⌊mT⌋∑d|Tμ(Td)dk
发现最后的 ∑d|Tμ(Td)dk 就是狄利克雷卷积的形式
令 g(n)=nk,f(n)=∑d|nμ(nd)g(d)
μ 和 g 都是积性函数,所以
那么可以用线性筛求 f
当
当 (a,b)=1 时 f(ab)=f(a)f(b)
当 ab 不互质时,也就是用 f(pkii) 和 pi 计算 f(pki+1i) 时,利用莫比乌斯函数的性质,发现只有 μ(1) 和 μ(pi) 是有价值的
f(pkii)=μ(1)∗(pkii)k+μ(pi)∗(pki−1i)k
f(pki+1i)=μ(1)∗(pki+1i)k+μ(pi)∗(pkii)k
也就是说 f(pki+1i)=f(pkii)∗pki
那么就可以筛筛筛了
计算出来 f(n) 了之后原式变成了
∑T=1n⌊nT⌋⌊mT⌋f(T)
预处理出 f(n) 的前缀和,只有 O(n−−√+m−−√) 种取值
分块求解
时间 O(n+T(n−−√+m−−√))
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define Mod 1000000007
#define LL long long
#define N 5000005
int T,n,m,k;
int p[N],prime[N];
LL ans,f[N];
LL fast_pow(LL a,int p)
{
LL ans=1;
for (;p;p>>=1,a=a*a%Mod)
if (p&1)
ans=ans*a%Mod;
return ans;
}
void get(int n)
{
f[1]=1;
for (int i=2;i<=n;++i)
{
if (!p[i])
{
prime[++prime[0]]=i;
f[i]=(fast_pow(i,k)-1+Mod)%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]*fast_pow(prime[j],k)%Mod;
break;
}
else f[i*prime[j]]=f[i]*f[prime[j]]%Mod;
}
}
for (int i=2;i<=n;++i) f[i]=(f[i]+f[i-1])%Mod;
}
int main()
{
scanf("%d%d",&T,&k);
get(5000000);
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+=(f[j]-f[i-1])*(n/i)%Mod*(m/i)%Mod;
ans=(ans%Mod+Mod)%Mod;
}
printf("%lld\n",ans);
}
}