题意:给定n、m,求 ∑ i = 1 n ∑ j = 1 m d ( i j ) \sum_{i=1}^n\sum_{j=1}^md(ij) ∑i=1n∑j=1md(ij)
推导:
1、有个结论: d ( i j ) = ∑ x ∣ i ∑ y ∣ j [ g c d ( x , y ) = 1 ] d(ij)=\sum_{x|i}\sum_{y|j}[gcd(x,y)=1] d(ij)=∑x∣i∑y∣j[gcd(x,y)=1]
∑ i = 1 n ∑ j = 1 m d ( i j ) = ∑ i = 1 n ∑ j = 1 m ∑ x ∣ i ∑ y ∣ j [ g c d ( x , y ) = 1 ] \sum_{i=1}^n\sum_{j=1}^m d(ij)=\sum_{i=1}^n\sum_{j=1}^m \sum_{x|i}\sum_{y|j}[gcd(x,y)=1] i=1∑nj=1∑md(ij)=i=1∑nj=1∑mx∣i∑y∣j∑[gcd(x,y)=1]
2、枚举倍数
∑ x = 1 n ∑ y = 1 m ∑ x ∣ i n ∑ y ∣ j m [ g c d ( x , y ) = 1 ] \sum_{x=1}^n\sum_{y=1}^m\sum_{x|i}^n\sum_{y|j}^m[gcd(x,y)=1] x=1∑ny=1∑mx∣i∑ny∣j∑m[gcd(x,y)=1]
3、化简并且利用莫比乌斯函数的性质换元
∑ x = 1 n ∑ y = 1 m ⌊ n x ⌋ ⌊ m x ⌋ ∑ d ∣ g c d ( x , y ) μ ( d ) \sum_{x=1}^n\sum_{y=1}^m {\lfloor \frac nx \rfloor} {\lfloor \frac mx\rfloor} \sum_{d|gcd(x,y)} \mu(d) x=1∑ny=1∑m⌊xn⌋⌊xm⌋d∣gcd(x,y)∑μ(d)
4、枚举d,并且设n
5、仔细观察这个式子,其实是可以再继续化简的, [ d ∣ x ] 、 [ d ∣ y ] [d|x]、[d|y] [d∣x]、[d∣y]中枚举的是d倍数,因此可以化简为:
∑ d = 1 n μ ( d ) ∑ x = 1 n ⌊ n x ⌋ [ d ∣ x ] ∑ y = 1 m ⌊ m x ⌋ [ d ∣ y ] \sum_{d=1}^n \mu(d) \sum_{x=1}^{n} {\lfloor \frac nx \rfloor}[d|x] \sum_{y=1}^m{\lfloor \frac mx \rfloor}[d|y] d=1∑nμ(d)x=1∑n⌊xn⌋[d∣x]y=1∑m⌊xm⌋[d∣y]
∑ d = 1 n μ ( d ) ∑ i = 1 ⌊ n d ⌋ ⌊ n d i ⌋ ∑ j = 1 ⌊ m d ⌋ ⌊ m d j ⌋ \sum_{d=1}^n \mu(d) \sum_{i=1}^{\lfloor \frac nd \rfloor} {\lfloor \frac n{di} \rfloor} \sum_{j=1}^{\lfloor \frac md \rfloor}{\lfloor \frac m{dj} \rfloor} d=1∑nμ(d)i=1∑⌊dn⌋⌊din⌋j=1∑⌊dm⌋⌊djm⌋
6、然后我们设 f ( x ) = ∑ i = 1 x ⌊ x i ⌋ f(x)=\sum_{i=1}^x {\lfloor \frac xi \rfloor} f(x)=∑i=1x⌊ix⌋,原式就可以化简为
∑ d = 1 n μ ( d ) f ( n d ) f ( m d ) \sum_{d=1}^n \mu(d) f(\frac nd) f(\frac md) d=1∑nμ(d)f(dn)f(dm)
7、同时 f ( x ) f(x) f(x)恰好是[1,x]中每个数的约数的个数之和,因此可以线性筛处理d[i],然后作前缀和即可
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5,maxm=1e5+5;
const int mod=1e9+7,inf=0x7f7f7f7f;
const int N=5e4;
int visit[N+10],prime[N+10],cnt;
int mu[N+10],f[N+10],d[N+10],num[N+10];
void init()
{
mu[1]=1,cnt=0,d[1]=1;
for(int i=2;i<=N;++i)
{
if(!visit[i])
prime[++cnt]=i,num[i]=1,d[i]=2,mu[i]=-1;
for(int j=1;j<=cnt&&i*prime[j]<=N;++j)
{
visit[i*prime[j]]=1;
if(i%prime[j]==0)
{
d[i*prime[j]]=d[i]/(num[i]+1)*(num[i]+2);
num[i*prime[j]]=num[i]+1;
break;
}
mu[i*prime[j]]=-mu[i];
num[i*prime[j]]=1;
d[i*prime[j]]=d[i]*2;
}
}
for(int i=1;i<=N;++i)
mu[i]+=mu[i-1],f[i]=f[i-1]+d[i];
}
int t,n,m;
int main()
{
init();
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
if(n>m)
swap(n,m);
int l=1,r;
ll ans=0;
while(l<=n)
{
r=min(n/(n/l),m/(m/l));
ans+=1ll*(mu[r]-mu[l-1])*f[n/l]*f[m/l];
l=r+1;
}
printf("%lld\n",ans);
}
return 0;
}