题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2820
题意:
求二元组
(
x
,
y
)
(x,y)
(x,y)的个数,满足
1
≤
x
≤
n
,
1
≤
y
≤
m
1 \le x \le n,1 \le y \le m
1≤x≤n,1≤y≤m,且
g
c
d
(
x
,
y
)
gcd(x,y)
gcd(x,y)为素数
题解:
令
P
P
P为素数集合,以下除法均为整除
Σ
p
∈
P
Σ
i
=
1
n
Σ
j
=
1
m
[
g
c
d
(
i
,
j
)
=
=
p
]
\large \Sigma_{p \in P}\Sigma_{i=1}^n\Sigma_{j=1}^m [gcd(i,j)==p]
Σp∈PΣi=1nΣj=1m[gcd(i,j)==p]
=
Σ
p
∈
P
Σ
i
=
1
n
/
p
Σ
j
=
1
m
/
p
[
g
c
d
(
i
,
j
)
=
=
1
]
\large =\Sigma_{p \in P}\Sigma_{i=1}^{n/p}\Sigma_{j=1}^{m/p} [gcd(i,j)==1]
=Σp∈PΣi=1n/pΣj=1m/p[gcd(i,j)==1]
e
∗
1
=
μ
e * 1 = \mu
e∗1=μ可得
=
Σ
p
∈
P
Σ
i
=
1
n
/
p
Σ
j
=
1
m
/
p
Σ
d
∣
x
,
d
∣
y
μ
(
d
)
\large =\Sigma_{p \in P}\Sigma_{i=1}^{n/p}\Sigma_{j=1}^{m/p} \Sigma_{d|x,d|y}\mu(d)
=Σp∈PΣi=1n/pΣj=1m/pΣd∣x,d∣yμ(d)
枚举
d
d
d,交换枚举顺序可得:
=
Σ
p
∈
P
Σ
d
=
1
m
i
n
(
n
,
m
)
p
μ
(
d
)
[
n
p
d
]
[
m
p
d
]
\large =\Sigma_{p \in P}\Sigma_{d=1}^{min(n,m)\over p}\mu(d)[{n\over pd}][{m\over pd}]
=Σp∈PΣd=1pmin(n,m)μ(d)[pdn][pdm]
=
Σ
t
=
1
m
i
n
(
n
,
m
)
[
n
t
]
[
m
t
]
Σ
p
∈
P
,
p
∣
t
μ
(
t
p
)
\large =\Sigma_{t=1}^{min(n,m)}[{n\over t}][{m\over t}]\Sigma_{p \in P,p|t}\mu({t\over p})
=Σt=1min(n,m)[tn][tm]Σp∈P,p∣tμ(pt)
前部分分块即可,后部分我们继续考虑反演
令后半部分为
g
(
n
)
g(n)
g(n),即
g
(
n
)
=
Σ
p
∈
P
,
p
∣
n
μ
(
n
p
)
g(n)=\Sigma_{p \in P,p|n}\mu({n \over p})
g(n)=Σp∈P,p∣nμ(pn)
=
Σ
t
=
1
m
i
n
(
n
,
m
)
[
n
t
]
[
m
t
]
g
(
t
)
\large =\Sigma_{t=1}^{min(n,m)}[{n\over t}][{m\over t}]g(t)
=Σt=1min(n,m)[tn][tm]g(t)
g
(
t
)
g(t)
g(t)可以通过前缀和算出来(分块的话不是一个
t
t
t)
代码:
// by Balloons
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mpr make_pair
#define debug() puts("okkkkkkkk")
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
using namespace std;
typedef long long LL;
const int inf = 1 << 30;
const int maxn=1e7+5;
int n,m;
int notpm[maxn],pm[maxn],pcnt=0;
int mu[maxn];
LL cnt[maxn];
void xxs(){
notpm[1]=mu[1]=1;
for(int i=2;i<=maxn-5;i++){
if(!notpm[i]){
pm[++pcnt]=i;mu[i]=-1;
}
for(int j=1;j<=pcnt && pm[j]*i<=maxn-5; j++){
notpm[i*pm[j]]=1;
if(i%pm[j] == 0){
mu[i*pm[j]] = 0;
break;
}
mu[i*pm[j]]=-mu[i];
}
}
}
void init(){
for(int i=1;i<=pcnt;i++){
for(int j=pm[i];j<=maxn - 5;j+=pm[i])cnt[j] += 1ll*mu[j/pm[i]];
}
}
void fk(){
int i=1,j=0;
LL ans=0;
for(;i<=n && i<=m; i=j+1){
j=min(n/(n/i),m/(m/i));
ans+=1ll*(n/i)*(m/i)*(cnt[j]-cnt[i-1]);
}
printf("%lld\n",ans);
}
int main(){
int Te;scanf("%d",&Te);
xxs();init();
for(int i=1;i<=maxn-5;i++)cnt[i]+=cnt[i-1];
while(Te--){
scanf("%d%d",&n,&m);
fk();
}
return 0;
}