一、题目
二、解法
首先证明一个结论:
d
(
i
,
j
)
=
∑
x
∣
i
∑
y
∣
j
[
gcd
(
x
,
y
)
=
1
]
d(i,j)=\sum_{x|i}\sum_{y|j}[\gcd(x,y)=1]
d(i,j)=x∣i∑y∣j∑[gcd(x,y)=1]证明考虑单个质因数
p
p
p,设
i
i
i中有
p
a
p^a
pa,
j
j
j中有
p
b
p^b
pb,等式右边的贡献是
a
+
b
+
1
a+b+1
a+b+1,等式左边考虑
x
x
x中没有
p
p
p,贡献为
b
b
b;
y
y
y中没有
p
p
p,贡献为
a
a
a;
x
,
y
x,y
x,y都没有
p
p
p,贡献为
1
1
1,总贡献也是
a
+
b
+
1
a+b+1
a+b+1,等式右边的每个质因数互相独立,可以理解为枚举了所有情况相当于所有贡献的乘积,证毕。
现在用上面的结论来推式子:
∑
i
=
1
n
∑
j
=
1
m
∑
x
∣
i
∑
y
∣
j
[
gcd
(
x
,
y
)
=
1
]
\sum_{i=1}^n\sum_{j=1}^m\sum_{x|i}\sum_{y|j}[\gcd(x,y)=1]
i=1∑nj=1∑mx∣i∑y∣j∑[gcd(x,y)=1]我们枚举
x
,
y
x,y
x,y,这样
i
,
j
i,j
i,j的取值我们就知道了:
∑
x
=
1
n
∑
y
=
1
m
n
x
×
m
y
[
gcd
(
x
,
y
)
=
1
]
\sum_{x=1}^n\sum_{y=1}^m \frac{n}{x}\times\frac{m}{y}[\gcd(x,y)=1]
x=1∑ny=1∑mxn×ym[gcd(x,y)=1]
gcd
\gcd
gcd是很容易反演的,搞一波莫比乌斯反演:
f
(
i
)
=
∑
x
=
1
n
∑
y
=
1
m
n
x
×
m
y
[
gcd
(
x
,
y
)
=
i
]
f(i)=\sum_{x=1}^n\sum_{y=1}^m \frac{n}{x}\times\frac{m}{y}[\gcd(x,y)=i]
f(i)=x=1∑ny=1∑mxn×ym[gcd(x,y)=i]
F
(
i
)
=
∑
x
=
1
n
∑
y
=
1
m
n
x
×
m
y
[
i
∣
gcd
(
x
,
y
)
]
=
∑
i
∣
d
f
(
d
)
F(i)=\sum_{x=1}^n\sum_{y=1}^m \frac{n}{x}\times\frac{m}{y}[i|\gcd(x,y)]=\sum_{i|d}f(d)
F(i)=x=1∑ny=1∑mxn×ym[i∣gcd(x,y)]=i∣d∑f(d)
f
(
i
)
=
∑
i
∣
d
μ
(
d
i
)
F
(
d
)
f(i)=\sum_{i|d}\mu(\frac{d}{i})F(d)
f(i)=i∣d∑μ(id)F(d)我们要求的是
f
(
1
)
f(1)
f(1):
f
(
1
)
=
∑
i
=
1
n
μ
(
i
)
F
(
i
)
f(1)=\sum_{i=1}^n\mu(i)F(i)
f(1)=i=1∑nμ(i)F(i)问题变成了如何求
F
(
i
)
F(i)
F(i),继续推式子,考虑消去
gcd
\gcd
gcd的影响:
F
(
i
)
=
∑
x
=
1
n
/
i
∑
y
=
1
m
/
i
n
x
i
m
y
i
F(i)=\sum_{x=1}^{n/i}\sum_{y=1}^{m/i}\frac{n}{xi}\frac{m}{yi}
F(i)=x=1∑n/iy=1∑m/ixinyim只要我们知道了
s
(
x
)
=
∑
i
=
1
x
x
i
s(x)=\sum_{i=1}^x \frac{x}{i}
s(x)=∑i=1xix,那么
F
(
i
)
F(i)
F(i)也就迎刃而解了,
s
(
i
)
s(i)
s(i)是可以通过分块
O
(
n
n
)
O(n\sqrt n)
O(nn)预处理的,至于询问也可以用分块解决,时间复杂度
O
(
T
n
)
O(T\sqrt n)
O(Tn),贴个代码
q
w
q
qwq
qwq
#include <cstdio>
#include <iostream>
using namespace std;
#define int long long
const int M = 50005;
int read()
{
int x=0,flag=1;
char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int T,n,m,cnt,p[M],vis[M],mu[M],s[M];
void init(int n)
{
mu[1]=1;
for(int i=2;i<=n;i++)
{
if(!vis[i])
{
p[++cnt]=i;
mu[i]=-1;
}
for(int j=1;j<=cnt && i*p[j]<=n;j++)
{
vis[i*p[j]]=1;
if(i%p[j]==0) break;
mu[i*p[j]]=-mu[i];
}
}
for(int i=1;i<=n;i++)
{
mu[i]+=mu[i-1];
for(int l=1,r;l<=i;l=r+1)
{
r=i/(i/l);
s[i]+=(r-l+1)*(i/l);
}
}
}
signed main()
{
T=read();
init(5e4);
while(T--)
{
n=read();m=read();
if(n>m) swap(n,m);
int ans=0;
for(int l=1,r;l<=n;l=r+1)
{
r=min(n/(n/l),m/(m/l));
ans+=(mu[r]-mu[l-1])*s[n/l]*s[m/l];
}
printf("%lld\n",ans);
}
}