Description
神犇YY虐完数论后给傻×kAc出了一题
给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对
kAc这种傻×必然不会了,于是向你来请教……
多组输入
Input
第一行一个整数T 表述数据组数
接下来T行,每行两个正整数,表示N, M
Output
T行,每行一个整数表示第i组数据的结果
Sample Input
2
10 10
100 100
Sample Output
30
2791
HINT
T = 10000
N, M <= 10000000
Source
跟这个一样:
【bzoj2818】Gcd 欧拉函数
不过是多组数据,每组不能O(n)做了…
所以这样:
∑
p
是
素
数
∑
i
<
=
n
∑
j
<
=
m
g
c
d
(
i
,
j
)
=
p
=
∑
p
是
素
数
∑
i
<
=
n
/
p
∑
j
<
=
m
/
p
e
(
g
c
d
(
i
,
j
)
)
=
∑
p
是
素
数
∑
i
<
=
n
/
p
∑
j
<
=
m
/
p
∑
d
|
i
d
|
j
μ
(
d
)
=
∑
p
是
素
数
∑
d
<
=
m
i
n
(
n
/
p
,
m
/
p
)
μ
(
d
)
∑
i
<
=
n
/
p
∑
j
<
=
m
/
p
[
d
|
i
d
|
j
]
=
∑
p
是
素
数
∑
d
<
=
m
i
n
(
n
/
p
,
m
/
p
)
μ
(
d
)
∗
⌊
n
p
d
⌋
∗
⌊
m
p
d
⌋
令
k
=
p
d
。
=
∑
p
是
素
数
∑
k
<
=
m
i
n
(
n
,
m
)
p
|
k
μ
(
k
p
)
∗
⌊
n
k
⌋
∗
⌊
m
k
⌋
设
f
(
k
)
=
∑
p
|
k
p
是
素
数
μ
(
k
p
)
。
所以答案就是
∑
k
<
=
m
i
n
(
n
,
m
)
f
(
k
)
∗
⌊
n
k
⌋
∗
⌊
m
k
⌋
f
(
k
)
可以筛。
然后就能
O
(
n
√
)
回答了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long LL;
const int SZ = 10000010;
const int MAXN = 10000000;
bool vis[SZ];
int pri[SZ],mu[SZ];
LL f[SZ],sum[SZ];
void shai()
{
mu[1] = 1;
int tot = 0;
for(int i = 2;i <= MAXN;i ++)
{
if(!vis[i]) pri[++ tot] = i,mu[i] = -1;
for(int j = 1,m;j <= tot && (m = i * pri[j]) <= MAXN;j ++)
{
vis[m] = 1;
if(i % pri[j] == 0) { mu[m] = 0; break; }
else mu[m] = -mu[i];
}
}
for(int i = 1;i <= tot;i ++)
{
for(int j = pri[i];j <= MAXN;j += pri[i])
{
f[j] += mu[j / pri[i]];
}
}
for(int i = 1;i <= MAXN;i ++)
sum[i] = sum[i - 1] + f[i];
}
LL ask(int n,int m)
{
LL ans = 0;
if(n > m) swap(n,m);
for(int i = 1,r;i <= n;i = r + 1)
{
r = min(n / (n / i),m / (m / i));
ans += (sum[r] - sum[i - 1]) * (n / i) * (m / i);
}
return ans;
}
int main()
{
int T;
scanf("%d",&T);
shai();
while(T --)
{
int n,m;
scanf("%d%d",&n,&m);
printf("%lld\n",ask(n,m));
}
return 0;
}