洛谷P2257 YY的gcd 莫比乌斯反演+整除分块

题目链接:
洛谷

莫比乌斯反演+整除分块 q w q qwq qwq
如果不会莫比乌斯反演,珂以看我的博客qwq
做这道题之前珂以先看HDU1695和我的题解qwq

先把答案表示出来:
a n s = Σ i = 1 N Σ j = 1 M [ g c d ( i , j ) 为 质 数 ] ans=\Large\Sigma\large_{i=1}^N\Large\Sigma\large_{j=1}^M[gcd(i,j)为质数] ans=Σi=1NΣj=1M[gcd(i,j)]
发现“为质数”不太好转化,珂以考虑把 g c d ( i , j ) gcd(i,j) gcd(i,j)提前枚举:
= Σ p 为 质 数 Σ i = 1 N Σ j = 1 M [ g c d ( i , j ) = = p ] =\Large\Sigma\large_{p为质数}\Large\Sigma\large_{i=1}^N\Large\Sigma\large_{j=1}^M[gcd(i,j)==p] =ΣpΣi=1NΣj=1M[gcd(i,j)==p]
h d u 1695 hdu1695 hdu1695的推法,这里珂以把 i , j i,j i,j同时除以 p p p
= Σ p 为 质 数 Σ i = 1 N / p Σ j = 1 M / p [ g c d ( i , j ) = = 1 ] =\Large\Sigma\large_{p为质数}\Large\Sigma\large_{i=1}^{N/p}\Large\Sigma\large_{j=1}^{M/p}[gcd(i,j)==1] =ΣpΣi=1N/pΣj=1M/p[gcd(i,j)==1]
f ( n ) f(n) f(n)表示 g c d ( i , j ) = = n gcd(i,j)==n gcd(i,j)==n的个数, F ( n ) F(n) F(n)表示 n ∣ g c d ( i , j ) n|gcd(i,j) ngcd(i,j)的个数。
F ( n ) = Σ n ∣ d f ( d ) F(n)=\Large\Sigma\large_{n|d}f(d) F(n)=Σndf(d)
做一下莫比乌斯反演得 f ( n ) = Σ n ∣ d μ ( d n ) F ( d ) = Σ n ∣ d μ ( d n ) ⌊ N d ⌋ ⌊ M d ⌋ f(n)=\Large\Sigma\large_{n|d}\mu(\frac{d}{n})F(d)=\Large\Sigma\large_{n|d}\mu(\frac{d}{n})\lfloor\frac{N}{d}\rfloor\lfloor\frac{M}{d}\rfloor f(n)=Σndμ(nd)F(d)=Σndμ(nd)dNdM
所以
a n s = Σ p 为 质 数 Σ p ∣ d μ ( d p ) F ( d ) ans=\Large\Sigma\large_{p为质数}\Large\Sigma\large_{p|d}\mu(\frac{d}{p})F(d) ans=ΣpΣpdμ(pd)F(d)
d p = t \frac{d}{p}=t pd=t,把式子改为枚举 t t t
a n s = Σ p 为 质 数 Σ t = 1 m i n ( n , m ) / p μ ( t ) F ( t p ) = Σ p 为 质 数 Σ t = 1 m i n ( n , m ) / p μ ( t ) ⌊ N t p ⌋ ⌊ M t p ⌋ ans=\Large\Sigma\large_{p为质数}\Large\Sigma\large_{t=1}^{min(n,m)/p}\mu(t)F(tp)=\Large\Sigma\large_{p为质数}\Large\Sigma\large_{t=1}^{min(n,m)/p}\mu(t)\lfloor\frac{N}{tp}\rfloor\lfloor\frac{M}{tp}\rfloor ans=ΣpΣt=1min(n,m)/pμ(t)F(tp)=ΣpΣt=1min(n,m)/pμ(t)tpNtpM
T = t p T=tp T=tp,则
a n s = Σ Σ μ ( T t ) ⌊ N T ⌋ ⌊ M T ⌋ ans=\Large\Sigma\large\Large\Sigma\large\mu(\frac{T}{t})\lfloor\frac{N}{T}\rfloor\lfloor\frac{M}{T}\rfloor ans=ΣΣμ(tT)TNTM
= Σ T = 1 m i n ( n , m ) ⌊ N T ⌋ ⌊ M T ⌋ Σ t ∣ T μ ( T t ) =\Large\Sigma\large_{T=1}^{min(n,m)}\lfloor\frac{N}{T}\rfloor\lfloor\frac{M}{T}\rfloor\Large\Sigma\large_{t|T}\mu(\frac{T}{t}) =ΣT=1min(n,m)TNTMΣtTμ(tT)
然后整除分块+前缀和就珂以了qwq

上代码:

#include
#include
#define re register int
using namespace std;
typedef long long ll;
int read() {
	re x=0,f=1;
	char ch=getchar();
	while(ch<'0' || ch>'9') {
		if(ch=='-')	f=-1;
		ch=getchar();
	}
	while(ch>='0' && ch<='9') {
		x=10*x+ch-'0';
		ch=getchar();
	}
	return x*f;
}
const int Size=10000005;
ll n,m,sum[Size],f[Size];
int tot,p[Size],prime[Size/10]; 
bool vis[Size];
void getp(int maxn) {
	p[1]=1;
	for(re i=2; i<=maxn; i++) {
		if(!vis[i]) {
			p[i]=-1;
			prime[++tot]=i;
		}
		for(re j=1; j<=tot && i*prime[j]<=maxn; j++) {
			vis[i*prime[j]]=true;
			if(i%prime[j]==0)	break;
			p[i*prime[j]]=-p[i];
		}
	}
	for(re i=1; i<=tot; i++) {
		for(re j=1; j*prime[i]<=maxn; j++) {
			f[j*prime[i]]+=p[j];
		}
	}
	for(re i=1; i<=maxn; i++) {
//		sum[i]+=sum[i-1];
		sum[i]=sum[i-1]+f[i];
	}
}
int main() {
	getp(10000000);
	int T=read();
	while(T--) {
		n=read();
		m=read();
		int maxn=min(n,m),lst;
		ll ans=0;
		for(re i=1; i<=maxn; i=lst+1) {
			lst=min(n/(n/i),m/(m/i));
			ans+=(ll)(n/i)*(m/i)*(sum[lst]-sum[i-1]);
		}
		printf("%lld\n",ans);
	}
	return 0;
}

你可能感兴趣的:(Luogu题目)