神犇 YY 虐完数论后给傻× kAc 出了一题
给定 N,M 求 1≤x≤N,1≤y≤M 且 gcd(x,y) 为质数的 (x,y) 有多少对。
======p∈prim∑i=1∑nj=1∑m[gcd(i,j)=p]p∈prim∑i=1∑⌊pn⌋j=1∑⌊pm⌋[gcd(i,j)=1]p∈prim∑i=1∑⌊pn⌋j=1∑⌊pm⌋ε(gcd(i,j)=1)p∈prim∑i=1∑⌊pn⌋j=1∑⌊pm⌋ε(gcd(i,j))p∈prim∑i=1∑⌊pn⌋j=1∑⌊pm⌋d∣gcd(i,j)∑μ(d)p∈prim∑p∣d∑μ(d)i=1∑⌊pn⌋[d∣i]j=1∑⌊pm⌋[d∣j]p∈prim∑p∣d∑μ(d)⌊kdn⌋kdm⌋
设:
f(p)=p∣d∑μ(d)
则原式化为:
=p∈prim∑f(p)×⌊kdn⌋kdm⌋
我们先去预处理 f 函数
for(int i=1;i<=cnt;i++)
for(int j=1;j*prim[i]<N;j++)
f[j*prim[i]]+=mu[j];
就是这里的 f 数组。
之后我们就可以求解了。
我们可以使用数论分块来写这题。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<typename T>inline void read(T &FF){
T RR=1;FF=0;char CH=getchar();
for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
FF*=RR;
}
const int N=1e7+10;
int prim[N],mu[N],sum[N],cnt,k,T,f[N];
bool vis[N];
void init(){
mu[1]=1;
for(register int i=2;i<N;i++){
if(!vis[i]){
mu[i]=-1;
prim[++cnt]=i;
}
for(register int j=1;j<=cnt&&i*prim[j]<N;j++){
vis[i*prim[j]]=1;
if(i%prim[j]==0)break;
mu[i*prim[j]]=-mu[i];
}
}
for(int i=1;i<=cnt;i++)
for(int j=1;j*prim[i]<N;j++)
f[j*prim[i]]+=mu[j];
for(register int i=1;i<N;i++)sum[i]=sum[i-1]+f[i];
}
ll calc(int a,int b){
ll ans=0;
for(register int l=1,r;l<=min(a,b);l=r+1){
r=min(a/(a/l),b/(b/l));
ans+=(1ll*a/l)*(1ll*b/l)*(sum[r]-sum[l-1]);
}
return ans;
}
int main(){
init();
for(read(T);T--;){
int x,y;
read(x);read(y);
printf("%lld
",calc(x,y));
}
return 0;
}