Description
给下N,M,K.求
Input
输入有多组数据,输入数据的第一行两个正整数T,K,代表有T组数据,K的意义如上所示,下面第二行到第T+1行,每行为两个正整数N,M,其意义如上式所示。
Output
如题
Sample Input
1 2
3 3
Sample Output
20
HINT
1<=N,M,K<=5000000,1<=T<=2000
分析:一道非常显然的莫比乌斯反演题目啦。不过要知道的是两个积性函数的狄利克雷卷积也是一个积性函数。
代码:
// luogu-judger-enable-o2
#include <iostream>
#include <cstdio>
#include <cmath>
#define LL long long
const LL maxn=5e6+7;
const LL mod=1000000007;
using namespace std;
LL test,n,m,k,cnt;
LL prime[maxn],not_prime[maxn];
LL f[maxn],g[maxn];
LL power(LL x,LL y)
{
if (y==1) return x;
LL d=power(x,y/2);
d=(d*d)%mod;
if (y%2) d=(d*x)%mod;
return d;
}
void getmul(LL n)
{
f[1]=1;
for (LL i=2;i<=n;i++)
{
if (!not_prime[i])
{
prime[++cnt]=i;
g[i]=power((LL)i,k);
f[i]=(g[i]+mod-1)%mod;
}
for (LL j=1;j<=cnt;j++)
{
if (i*prime[j]>n) break;
not_prime[i*prime[j]]=1;
if (i%prime[j]==0)
{
f[i*prime[j]]=(f[i]*g[prime[j]])%mod;
break;
}
f[i*prime[j]]=(f[i]*f[prime[j]])%mod;
}
}
for (LL i=1;i<=n;i++) f[i]=(f[i-1]+f[i])%mod;
}
LL calc(LL n,LL m)
{
LL ans=0;
if (n>m) swap(n,m);
for (LL i=1,last;i<=n;i=last+1)
{
last=min(n/(n/i),m/(m/i));
ans=(LL)(ans+(n/i)*(m/i)%mod*(f[last]+mod-f[i-1])%mod)%mod;
}
return ans;
}
int main()
{
scanf("%lld%lld",&test,&k);
getmul(maxn);
while (test--)
{
scanf("%lld%lld",&n,&m);
printf("%lld\n",calc(n,m));
}
}