P3957YY的GCD
问题描述
神犇YY虐完数论后给傻×kAc出了一题
给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对
kAc这种傻×必然不会了,于是向你来请教……
输入格式
第一行一个整数T 表述数据组数
接下来T行,每行两个正整数,表示N, M
输出格式
T行,每行一个整数表示第i组数据的结果
样例输入
2
10 10
100 100
样例输出
30
2791
提示
T = 10000
N, M <= 10000000
显然
Ans=∑min(n,m)p∑ni=1∑mj=1[gcd(i,j)==p],p为质数
A
n
s
=
∑
p
m
i
n
(
n
,
m
)
∑
i
=
1
n
∑
j
=
1
m
[
g
c
d
(
i
,
j
)
==
p
]
,
p
为
质
数
如果是单组询问,到这里已经可以了,但本题有多组询问,因此
后面的部分可以直接枚举质数再枚举倍数预处理,复杂度接近 O(n) O ( n )
但显然可以线性筛处理,令其为 g[i] g [ i ] ,当 p[j]|i p [ j ] | i 时, g[i∗p[j]]=μ(i) g [ i ∗ p [ j ] ] = μ ( i ) ,否则 g[i∗p[j]]=mu[i]−g[i] g [ i ∗ p [ j ] ] = m u [ i ] − g [ i ]
然后分块处理即可,复杂度 O(n+Tn−−√) O ( n + T n )
代码:
#include<stdio.h>
#include<algorithm>
#define N 10000005
#define ll long long
using namespace std;
ll T,P[N],tot,mu[N],g[N];
bool mark[N];
void EU()
{
ll i,j;mu[1]=1;g[1]=0;
for(i=2;i<N;i++)
{
if(!mark[i])P[++tot]=i,mu[i]=-1,g[i]=1;
for(j=1;j<=tot&&i*P[j]<N;j++)
if(i%P[j])mu[i*P[j]]=-mu[i],g[i*P[j]]=mu[i]-g[i],mark[i*P[j]]=1;
else {mu[i*P[j]]=0;g[i*P[j]]=mu[i];mark[i*P[j]]=1;break;}
}
for(i=2;i<N;i++)g[i]+=g[i-1];
}
int main()
{
ll n,m,i,j,ans;
scanf("%lld",&T);EU();
while(T--)
{
scanf("%lld%lld",&n,&m);ans=0;
for(i=1;i<=n&&i<=m;i=j+1)
{
j=min(n/(n/i),m/(m/i));
ans+=(n/i)*(m/i)*(g[j]-g[i-1]);
}
printf("%lld\n",ans);
}
}