题目链接:点击这里
题目大意:
t
t
t 组数据,每组数据给出
N
,
M
N , M
N,M ,求
1
≤
x
≤
N
1 \leq x \leq N
1≤x≤N ,
1
≤
y
≤
M
1 \leq y \leq M
1≤y≤M 且
gcd
(
x
,
y
)
\gcd(x, y)
gcd(x,y) 为质数的二元组
(
x
,
y
)
(x, y)
(x,y) 的数目
题目分析:
题目所求式子为:
∑
i
=
1
N
∑
j
=
1
M
[
gcd
(
i
,
j
)
=
p
r
i
m
e
]
\sum_{i=1}^N\sum_{j=1}^M[\gcd(i,j)=prime]
i=1∑Nj=1∑M[gcd(i,j)=prime]
我们套路的设
F
(
n
)
F(n)
F(n)为
gcd
(
i
,
j
)
%
n
=
0
\gcd(i,j)\%n=0
gcd(i,j)%n=0 的个数 ,
f
(
d
)
f(d)
f(d) 为
gcd
(
i
,
j
)
=
d
\gcd(i,j)=d
gcd(i,j)=d 的个数,即:
F
(
n
)
=
∑
n
∣
d
f
(
d
)
=
⌊
N
n
⌋
⌊
M
n
⌋
F(n)=\sum_{n|d}f(d)=\lfloor \frac N n \rfloor \lfloor \frac M n \rfloor
F(n)=n∣d∑f(d)=⌊nN⌋⌊nM⌋
f
(
d
)
=
∑
i
=
1
N
∑
j
=
1
M
[
gcd
(
i
,
j
)
=
d
]
f(d) =\sum_{i=1}^N\sum_{j=1}^M[\gcd(i,j)=d]
f(d)=i=1∑Nj=1∑M[gcd(i,j)=d]
由莫比乌斯反演可得:
f
(
n
)
=
∑
n
∣
d
μ
(
⌊
d
n
⌋
)
F
(
d
)
f(n)=\sum_{n|d}μ(\lfloor \frac d n \rfloor)F(d)
f(n)=n∣d∑μ(⌊nd⌋)F(d)
于是题目所求可以变成:
∑
p
∈
p
r
i
m
e
f
(
p
)
=
∑
p
∈
p
r
i
m
e
∑
p
∣
d
μ
(
⌊
d
p
⌋
)
F
(
d
)
\sum_{p \in prime}f(p)=\sum_{p \in prime}\sum_{p|d}μ(\lfloor \frac d p \rfloor)F(d)
p∈prime∑f(p)=p∈prime∑p∣d∑μ(⌊pd⌋)F(d)
=
∑
p
∈
p
r
i
m
e
∑
d
=
1
m
i
n
(
⌊
N
n
⌋
,
⌊
M
n
⌋
)
μ
(
d
)
F
(
d
p
)
=\sum_{p \in prime}\sum_{d=1}^{min(\lfloor \frac N n \rfloor , \lfloor \frac M n \rfloor)} μ(d)F(dp)
=p∈prime∑d=1∑min(⌊nN⌋,⌊nM⌋)μ(d)F(dp)
=
∑
p
∈
p
r
i
m
e
∑
d
=
1
m
i
n
(
⌊
N
n
⌋
,
⌊
M
n
⌋
)
μ
(
d
)
⌊
N
d
p
⌋
⌊
M
d
p
⌋
=\sum_{p \in prime}\sum_{d=1}^{min(\lfloor \frac N n \rfloor , \lfloor \frac M n \rfloor)} μ(d)\lfloor \frac N {dp} \rfloor \lfloor \frac M {dp} \rfloor
=p∈prime∑d=1∑min(⌊nN⌋,⌊nM⌋)μ(d)⌊dpN⌋⌊dpM⌋
我们令
x
=
d
p
x=dp
x=dp ,此时有:
∑
p
∈
p
r
i
m
e
∑
x
=
1
m
i
n
(
N
,
M
)
μ
(
x
p
)
⌊
N
x
⌋
⌊
M
x
⌋
\sum_{p \in prime} \sum_{x=1}^{min(N,M)} μ(\frac x p)\lfloor \frac N {x} \rfloor \lfloor \frac M {x} \rfloor
p∈prime∑x=1∑min(N,M)μ(px)⌊xN⌋⌊xM⌋
=
∑
x
=
1
m
i
n
(
N
,
M
)
∑
p
∣
x
,
p
∈
p
r
i
m
e
μ
(
x
p
)
⌊
N
x
⌋
⌊
M
x
⌋
=\sum_{x=1}^{min(N,M)} \sum_{p|x,p \in prime} μ(\frac x p)\lfloor \frac N {x} \rfloor \lfloor \frac M {x} \rfloor
=x=1∑min(N,M)p∣x,p∈prime∑μ(px)⌊xN⌋⌊xM⌋
=
∑
x
=
1
m
i
n
(
N
,
M
)
⌊
N
x
⌋
⌊
M
x
⌋
∑
p
∣
x
,
p
∈
p
r
i
m
e
μ
(
x
p
)
=\sum_{x=1}^{min(N,M)} \lfloor \frac N {x} \rfloor \lfloor \frac M {x} \rfloor \sum_{p|x,p \in prime}μ(\frac x p)
=x=1∑min(N,M)⌊xN⌋⌊xM⌋p∣x,p∈prime∑μ(px)
推到这里就可以放心大胆的搞了,用整除分块来快速处理 ⌊ N n ⌋ \lfloor \frac N n \rfloor ⌊nN⌋ 和 ⌊ M n ⌋ \lfloor \frac M n \rfloor ⌊nM⌋ ,然后我们发现 μ ( x p ) μ(\frac x p) μ(px) 是可以提前处理的,我们提前打好这东西的前缀和然后套在整除分块中 O ( 1 ) O(1) O(1) 求出 ∑ p ∣ x , p ∈ p r i m e μ ( x p ) \sum_{p|x,p \in prime}μ(\frac x p) ∑p∣x,p∈primeμ(px) 即可,时间复杂度为 O ( t n ) O(t\sqrt n) O(tn)
具体细节见代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
int read()
{
int res = 0,flag = 1;
char ch = getchar();
while(ch<'0' || ch>'9')
{
if(ch == '-') flag = -1;
ch = getchar();
}
while(ch>='0' && ch<='9')
{
res = (res<<3)+(res<<1)+(ch^48);//res*10+ch-'0';
ch = getchar();
}
return res*flag;
}
const int maxn = 1e7+5;
const int mod = 1e9+7;
const double pi = acos(-1);
const double eps = 1e-8;
int cnt,pri[maxn],mu[maxn],g[maxn];
ll sum[maxn];
bool vis[maxn];
void get_mu() //筛莫比乌斯函数,求需要的函数的前缀和
{
mu[1] = vis[1] = 1;
for(int i = 2;i < maxn;i++)
{
if(!vis[i])
{
mu[i] = -1;
pri[++cnt] = i;
}
for(int j = 1;j <= cnt && i*pri[j] < maxn;j++)
{
vis[i*pri[j]] = true;
if(i%pri[j] != 0) mu[i*pri[j]] -= mu[i];
else break;
}
}
for(int i = 1;i <= cnt;i++)
for(int j = 1;j*pri[i] < maxn;j++)
g[j*pri[i]] += mu[j];
for(int i = 1;i < maxn;i++)
sum[i] = sum[i-1]+g[i];
}
int main()
{
int t = read();
get_mu();
while(t--)
{
int n = read(),m = read();
ll ans = 0;
for(int l = 1,r;l <= min(n,m);l = r+1) //整除分块
{
r = min(n/(n/l),m/(m/l));
ans += 1ll*(n/l)*(m/l)*(sum[r]-sum[l-1]);
}
printf("%lld\n",ans);
}
return 0;
}