2024-03-27

2024-03-27

GCD

= 题目描述 =

给定正整数 \(n\),求 \(1\le x,y\le n\)\(\gcd(x,y)\) 为素数的数对 \((x,y)\) 有多少对

= Solution =

\[\begin{align*} ans&=\sum_{p\in primes}\sum_{i=1}^n\sum_{j=1}^n[\gcd(i,j)=p] \newline &=\sum_{p\in primes}\sum_{i=1}^{\left\lfloor\frac{n}{p}\right\rfloor}\sum_{j=1}^{\left\lfloor\frac{n}{p}\right\rfloor}[\gcd(i,j)=1] \end{align*} \]

这个转挺常见的,要记住
继续转化

现在的 \(i,j\) 是没有顺序的

我们给他规定一个顺序,将 \(j\) 限制在 \([1,i]\)
所有 \(j>i\) 的情况都唯一对应了一种 \(j<i\) 的情况(i, j 交换即可)
所以规定顺序之后的答案要 ×2
发现 所有的 \(i=j\) 的情况都被重复计算了
但是只有 \(i=j=1\) 的时候会对答案贡献 \(1\)
把多出来的 1 减掉就行了

\[\therefore ans=\sum_{p\in primes}\left(2\times\sum_{i=1}^{\left\lfloor\frac{n}{p}\right\rfloor}\left(\sum_{j=1}^i[\gcd(i,j)=1]\right)-1\right)\newline \]

发现最里层括号套着的和式其实就是 \(\varphi(i)\)

\[ans=\sum_{p\in primes}\left(2\times\sum_{i=1}^{\left\lfloor\frac{n}{p}\right\rfloor}\varphi(i)-1\right) \]

线性筛求出素数和欧拉函数
欧拉函数做个前缀和

时间复杂度 \(O(n)\)

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

typedef long long ll;

const int N=1e7+100;

int primes[N],cntp;
bool st[N];
ll phi[N];

void init_p(int mx) {
	phi[1]=1;
	for(int i=2;i<=mx;i++) {
		if(!st[i]) primes[++cntp]=i,phi[i]=i-1;
		for(int j=1;i*primes[j]<=mx;j++) {
			st[i*primes[j]]=true;
			if(i%primes[j]==0) {
				phi[i*primes[j]]=phi[i]*primes[j]*1;
				break;
			}
			phi[i*primes[j]]=phi[i]*(primes[j]-1);
		}
	}
	for(int i=1;i<=mx;i++) phi[i]+=phi[i-1];
}

int n;

int main() {
	scanf("%d",&n);
	init_p(n);
	ll ans=0;
	for(int j=1;j<=cntp;j++) ans+=(2*phi[n/primes[j]]-1);
	printf("%lld\n",ans);
	
	return 0;
} 

YY的GCD

刚才那题的升级版
\(i\in[1,n],j\in[1,m] \ \ \ m,n\le10^7\)\(T\le10^4\) 组询问,求 \(\gcd(i,j)\) 是素数的 \((i,j)\) 对数

没做完

中间去给同学讲了一下上回考试的题
感觉这次语言组织能力就好多了

posted @ 2024-03-27 11:49  OrangeStar*  阅读(6)  评论(0编辑  收藏  举报