题意:设d(i)为i的约数的个数,给你N,M,求
解析:
引理:
证明:
1.若i,j互质,则该引理显然
2.若i,j不互质,我们考虑使用数学归纳法
若已有上述式子成立,我们再加入一个质数p
则
则我们考虑一下
1.若x,y都不含p因子,则有d(ij)的贡献
2.若只有x含有p因子,则产生a*d(ij)的贡献
3.若只有y含有p因子,则产生b*d(ij)的贡献
综上可得:
故引理得证
引理2:
回到题目中的式子:
我们设
这个直接分块就行了
则上式就
这个直接分块算一下就行了
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAX=5e4;
ll mu[MAX+10],sum[MAX+10];
int prime[MAX+10];
bool p[MAX+10];
int T,n,m,k,len;
void init(){
mu[1]=1;
for (int i=2;i<=MAX;i++) {
if (!p[i]) {
prime[++len]=i; mu[i]=-1;
}
for (int j=1;j<=len&&prime[j]*i<=MAX;j++) {
p[prime[j]*i]=1;
if (i%prime[j]==0) {
mu[prime[j]*i]=0; break;
} mu[prime[j]*i]=-mu[i];
}
}
for (int i=1;i<=MAX;i++) mu[i]+=mu[i-1];
for (int i=1;i<=MAX;i++) {
for (int j=1;j<=i;j=k+1){
k=i/(i/j);
sum[i]+=(k-j+1)*(i/j);
}
}
}
ll solve(int n,int m)
{
ll ans=0;
for (int i=1;i<=min(n,m);i=k+1)
{
k=min(n/(n/i),m/(m/i));
ans+=sum[n/i]*sum[m/i]*(mu[k]-mu[i-1]);
}
return ans;
}
int main()
{
scanf("%d",&T);
init();
while (T--){
scanf("%d%d",&n,&m);
cout << solve(n,m) << endl;
}
}