题解 P2257 【YY的GCD】

神犇 YY 虐完数论后给傻× kAc 出了一题

给定 N , M N, M N,M 1 ≤ x ≤ N 1 \leq x \leq N 1xN 1 ≤ y ≤ M 1 \leq y \leq M 1yM gcd ⁡ ( x , y ) \gcd(x, y) gcd(x,y) 为质数的 ( x , y ) (x, y) (x,y) 有多少对。

前置知识

  • 莫比乌斯反演
  • 数论分块
    ∑ p ∈ p r i m ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = p ] = ∑ p ∈ p r i m ∑ i = 1 ⌊ n p ⌋ ∑ j = 1 ⌊ m p ⌋ [ gcd ⁡ ( i , j ) = 1 ] = ∑ p ∈ p r i m ∑ i = 1 ⌊ n p ⌋ ∑ j = 1 ⌊ m p ⌋ ε ( gcd ⁡ ( i , j ) = 1 ) = ∑ p ∈ p r i m ∑ i = 1 ⌊ n p ⌋ ∑ j = 1 ⌊ m p ⌋ ε ( gcd ⁡ ( i , j ) ) = ∑ p ∈ p r i m ∑ i = 1 ⌊ n p ⌋ ∑ j = 1 ⌊ m p ⌋ ∑ d ∣ gcd ⁡ ( i , j ) μ ( d ) = ∑ p ∈ p r i m ∑ p ∣ d μ ( d ) ∑ i = 1 ⌊ n p ⌋ [ d ∣ i ] ∑ j = 1 ⌊ m p ⌋ [ d ∣ j ] = ∑ p ∈ p r i m ∑ p ∣ d μ ( d ) ⌊ n k d ⌋ ⌊ m k d ⌋ \begin{aligned} &\sum_{p\in prim}\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)=p] \\ =& \sum_{p\in prim}\sum_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{p}\rfloor}[\gcd(i,j)=1]\\ =& \sum_{p\in prim}\sum_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{p}\rfloor}\varepsilon(\gcd(i,j)=1)\\ =& \sum_{p\in prim}\sum_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{p}\rfloor}\varepsilon(\gcd(i,j))\\ =& \sum_{p\in prim}\sum_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{p}\rfloor} \sum_{d\mid \gcd(i,j)} \mu(d)\\ =&\sum_{p\in prim}\sum_{p\mid d} \mu(d)\sum_{i=1}^{\lfloor\frac{n}{p}\rfloor}[d\mid i]\sum_{j=1}^{\lfloor\frac{m}{p}\rfloor}[d\mid j]\\ =&\sum_{p\in prim}\sum_{p\mid d} \mu(d) \lfloor \frac{n}{kd} \rfloor\lfloor \frac{m}{kd} \rfloor\\ \end{aligned} ======pprimi=1nj=1m[gcd(i,j)=p]pprimi=1pnj=1pm[gcd(i,j)=1]pprimi=1pnj=1pmε(gcd(i,j)=1)pprimi=1pnj=1pmε(gcd(i,j))pprimi=1pnj=1pmdgcd(i,j)μ(d)pprimpdμ(d)i=1pn[di]j=1pm[dj]pprimpdμ(d)kdnkdm
    设:

f ( p ) = ∑ p ∣ d μ ( d ) f(p)=\sum\limits_{p\mid d} \mu(d) f(p)=pdμ(d)

则原式化为:

= ∑ p ∈ p r i m f ( p ) × ⌊ n k d ⌋ ⌊ m k d ⌋ \begin{aligned} =&\sum_{p\in prim} f(p)\times \lfloor \frac{n}{kd} \rfloor\lfloor \frac{m}{kd} \rfloor\\\end{aligned} =pprimf(p)×kdnkdm

我们先去预处理 f f f 函数

for(int i=1;i<=cnt;i++)
	for(int j=1;j*prim[i]<N;j++)
		f[j*prim[i]]+=mu[j];

就是这里的 f f f 数组。

之后我们就可以求解了。

我们可以使用数论分块来写这题。

代码:

#include 
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\n",calc(x,y));
	}
	return 0;
}

你可能感兴趣的:(数学,莫比乌斯反演,数论)