题目传送门
这是一个很有意思的莫反
这道题要你求
∑
i
=
1
n
∑
j
=
1
m
d
(
i
j
)
\displaystyle\sum_{i=1}^{n}\displaystyle\sum_{j=1}^{m}d(ij)
i=1∑nj=1∑md(ij)
d
(
)
d()
d()表示约数的个数
这里有一个结论需要记住就是:
d
(
i
,
j
)
=
∑
x
∣
i
∑
y
∣
j
[
g
c
d
(
x
,
y
)
=
1
]
d(i,j)=\displaystyle\sum_{x|i}^{}\displaystyle\sum_{y|j}^{}[gcd(x,y)=1]
d(i,j)=x∣i∑y∣j∑[gcd(x,y)=1]
具体证明就是:按情况分类,因数个数就是分情况考虑
如果
i
j
ij
ij中包含
a
k
a^k
ak那么在这两个
∑
∑
∑中就是枚举了
k
+
1
k+1
k+1次
a
0
a^0
a0(也就是一次都没有枚举过,也算一次),因为毕竟是因数和函数,性质我们都不好搞,所以搞一个比较熟悉的
g
c
d
gcd
gcd
那么这个式子就是:
∑
i
=
1
n
∑
j
=
1
m
∑
x
∣
i
∑
y
∣
j
[
g
c
d
(
x
,
y
)
=
1
]
\displaystyle\sum_{i=1}^{n}\displaystyle\sum_{j=1}^{m}\displaystyle\sum_{x|i}^{}\displaystyle\sum_{y|j}^{}[gcd(x,y)=1]
i=1∑nj=1∑mx∣i∑y∣j∑[gcd(x,y)=1]通过莫比乌斯反演我们可以知道
∑
i
=
1
n
∑
j
=
1
m
∑
x
∣
i
∑
y
∣
j
∑
d
∣
g
c
d
(
x
,
y
)
μ
(
d
)
\displaystyle\sum_{i=1}^{n}\displaystyle\sum_{j=1}^{m}\displaystyle\sum_{x|i}^{}\displaystyle\sum_{y|j}^{}\displaystyle\sum_{d|gcd(x,y)}^{}μ(d)
i=1∑nj=1∑mx∣i∑y∣j∑d∣gcd(x,y)∑μ(d)
交换枚举顺序
∑
d
=
1
m
i
n
(
n
,
m
)
μ
(
d
)
∑
i
=
1
n
/
d
∑
j
=
1
m
/
d
∑
x
∣
i
∑
y
∣
j
\displaystyle\sum_{d=1}^{min(n,m)}μ(d)\displaystyle\sum_{i=1}^{n/d}\displaystyle\sum_{j=1}^{m/d}\displaystyle\sum_{x|i}^{}\displaystyle\sum_{y|j}^{}
d=1∑min(n,m)μ(d)i=1∑n/dj=1∑m/dx∣i∑y∣j∑
继续交换枚举顺序
∑
d
=
1
m
i
n
(
n
,
m
)
μ
(
d
)
∑
x
=
1
n
/
d
∑
y
=
1
m
/
d
∑
i
=
1
n
/
(
d
∗
x
)
∑
j
=
1
m
/
(
d
∗
y
)
\displaystyle\sum_{d=1}^{min(n,m)}μ(d)\displaystyle\sum_{x=1}^{n/d}\displaystyle\sum_{y=1}^{m/d}\displaystyle\sum_{i=1}^{n/(d*x)}\displaystyle\sum_{j=1}^{m/(d*y)}
d=1∑min(n,m)μ(d)x=1∑n/dy=1∑m/di=1∑n/(d∗x)j=1∑m/(d∗y)
然后得到
∑
d
=
1
m
i
n
(
n
,
m
)
μ
(
d
)
∑
x
=
1
n
/
d
∑
y
=
1
m
/
d
[
n
d
∗
x
]
[
m
d
∗
y
]
\displaystyle\sum_{d=1}^{min(n,m)}μ(d)\displaystyle\sum_{x=1}^{n/d}\displaystyle\sum_{y=1}^{m/d}[\frac{n}{d*x}][\frac{m}{d*y}]
d=1∑min(n,m)μ(d)x=1∑n/dy=1∑m/d[d∗xn][d∗ym]
再进行分离,为啥?因为你前后无瓜!
∑
d
=
1
m
i
n
(
n
,
m
)
μ
(
d
)
(
∑
x
=
1
n
/
d
[
n
d
∗
x
]
)
(
∑
y
=
1
m
/
d
[
m
d
∗
y
]
)
\displaystyle\sum_{d=1}^{min(n,m)}μ(d)(\displaystyle\sum_{x=1}^{n/d}[\frac{n}{d*x}])(\displaystyle\sum_{y=1}^{m/d}[\frac{m}{d*y}])
d=1∑min(n,m)μ(d)(x=1∑n/d[d∗xn])(y=1∑m/d[d∗ym])
看这个东西:
(
∑
y
=
1
m
/
d
[
m
d
∗
y
]
)
(\displaystyle\sum_{y=1}^{m/d}[\frac{m}{d*y}])
(y=1∑m/d[d∗ym])
让
t
=
m
/
d
t=m/d
t=m/d那不就成了
(
∑
y
=
1
t
[
t
y
]
)
(\displaystyle\sum_{y=1}^{t}[\frac{t}{y}])
(y=1∑t[yt])
对这个进行数论分块,预处理一下
for(ll i=1;i<=N;i++)
{
for(ll l=1,r;l<=i;l=r+1)
{
r=i/(i/l);
check[i]+=(r-l+1)*(i/l);
}
}
因为到最后枚举的是
n
d
∗
x
\frac{n}{d*x}
d∗xn
有前面的一个
d
d
d这个问题
所以还要再进行一个数论分块(因为数组访问的,你每回计算的角标有大量的相等的情况)
#include<iostream>
using namespace std;
typedef long long ll;
const ll N = 50005;
ll check[N+5];
ll mu[N + 5], p[N + 5];
bool flg[N + 5];
void mobius() {
ll tot = 0;
mu[1] = 1;
for (ll i = 2; i <= N; ++i) {
if (!flg[i]) {
p[++tot] = i;
mu[i] = -1;
}
for (ll j = 1; j <= tot && i * p[j] <= N; ++j) {
flg[i * p[j]] = 1;
if (i % p[j] == 0) {
mu[i * p[j]] = 0;
break;
}
mu[i * p[j]] = -mu[i];
}
}
//数论分块要用到的前缀和
for (ll i = 1; i <= N; ++i) mu[i] += mu[i - 1];
for(ll i=1;i<=N;i++){
for(ll l=1,r;l<=i;l=r+1){
r=i/(i/l);
check[i]+=(r-l+1)*(i/l);
}//cout<<check[i]<<endl;
//if(i==50)exit(0);
}
}
int main(){
mobius();
int T;
cin>>T;
while(T--){
ll n,m,ans=0;
cin>>n>>m;
for(ll l=1,r;l<=min(m,n);l=r+1){
// cout<<check[l]<<" "<<l<<endl;
r=min(m/(m/l),n/(n/l));
ans+=(mu[r]-mu[l-1])*(check[m/l])*check[n/l];
// cout<<ans<<endl;
}
cout<<ans<<endl;
}
}