GCD 题解

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

n ≤ 1 0 7 n\le 10^7 n107

题解

做法1

题意即为求 S = ∑ 质 数 p ∣ n ∑ i = 1 n ∑ j = 1 n [ g c d ( i , j ) = p ] S=\sum_{质数p|n}\sum_{i=1}^n\sum_{j=1}^n[gcd(i,j)=p] S=pni=1nj=1n[gcd(i,j)=p]

常规操作化简 S = ∑ 质 数 p ∣ n ∑ i = 1 ⌊ n p ⌋ ∑ j = 1 ⌊ n p ⌋ [ gcd ⁡ ( i , j ) = 1 ] S=\sum_{质数p|n}\sum_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum_{j=1}^{\lfloor\frac{n}{p}\rfloor}[\gcd(i,j)=1] S=pni=1pnj=1pn[gcd(i,j)=1]

如果我们记 n ′ = ⌊ n p ⌋ , f ( i ) = ∑ a = 1 n ′ ∑ b = 1 n ′ [ gcd ⁡ ( a , b ) = i ] , g ( i ) = ∑ i ∣ d f ( d ) n'={\lfloor\frac{n}{p}\rfloor},f(i)=\sum_{a=1}^{n'}\sum_{b=1}^{n'}[\gcd(a,b)=i],g(i)=\sum_{i|d}f(d) n=pn,f(i)=a=1nb=1n[gcd(a,b)=i],g(i)=idf(d)

则展开 g ( i ) g(i) g(i)

g ( i ) = ∑ i ∣ d ∑ a = 1 n ′ ∑ b = 1 n ′ [ gcd ⁡ ( a , b ) = d ] g(i)=\sum_{i|d}\sum_{a=1}^{n'}\sum_{b=1}^{n'}[\gcd(a,b)=d] g(i)=ida=1nb=1n[gcd(a,b)=d]

常规操作 g ( i ) = ∑ a = 1 n ′ ∑ b = 1 n ′ [ i ∣ gcd ⁡ ( a , b ) ] = ∑ a = 1 ⌊ n ′ i ⌋ ∑ b = 1 ⌊ n ′ i ⌋ [ 1 ∣ g c d ( a , b ) ] = ⌊ n ′ i ⌋ 2 g(i)=\sum_{a=1}^{n'}\sum_{b=1}^{n'}\left[i|\gcd(a,b)\right]=\sum_{a=1}^{\lfloor\frac{n'}{i}\rfloor}\sum_{b=1}^{\lfloor\frac{n'}{i}\rfloor}[1|gcd(a,b)]=\left\lfloor\frac{n'}{i}\right\rfloor^2 g(i)=a=1nb=1n[igcd(a,b)]=a=1inb=1in[1gcd(a,b)]=in2

所以 S = ∑ 质 数 p ∣ n f ( p ) = ∑ 质 数 p ∣ n ∑ d = 1 d p ≤ n μ ( d ) g ( p ) = ∑ 质 数 p ∣ n ∑ d = 1 p d ≤ n μ ( d ) ⌊ n d p ⌋ 2 S=\sum_{质数p|n}f(p)=\sum_{质数p|n}\sum_{d=1}^{dp\le n}\mu\left(d\right)g(p)=\sum_{质数p|n}\sum_{d=1}^{pd\le n}\mu(d)\left\lfloor\frac{n}{dp}\right\rfloor^2 S=pnf(p)=pnd=1dpnμ(d)g(p)=pnd=1pdnμ(d)dpn2

接着有设 T = d p T=dp T=dp,这里由于 p , d p,d p,d具有对称性,交换求和次序有 S = ∑ T = 1 n ⌊ n T ⌋ 2 ∑ 质 数 p ∣ T μ ( T p ) S=\sum_{T=1}^{n}\lfloor\frac{n}{T}\rfloor^2\sum_{质数p|T}\mu\left({\frac{T}{p}}\right) S=T=1nTn2pTμ(pT)

然后 ∑ T = 1 n ⌊ n T ⌋ 2 \sum_{T=1}^{n}\lfloor\frac{n}{T}\rfloor^2 T=1nTn2可以整除分块,而后面的可以在筛一遍质数之后 O ( n ) O(\sqrt{n}) O(n )求出,于是复杂度就是 O ( n ) O(n) O(n),实际上远远跑不满

做法2

事实上,因为数对具有对称性,我们可以将 S S S稍稍变形得到

S = ∑ 质 数 p ∣ n ∑ i = 1 ⌊ n p ⌋ ∑ j = 1 ⌊ n p ⌋ [ gcd ⁡ ( i , j ) = 1 ] = ∑ 质 数 p ∣ n ( 2 ∑ i = 1 ⌊ n p ⌋ ∑ j = 1 i [ gcd ⁡ ( i , j ) = 1 ] − 1 ) S=\sum_{质数p|n}\sum_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum_{j=1}^{\lfloor\frac{n}{p}\rfloor}[\gcd(i,j)=1]=\sum_{质数p|n}\left(2\sum_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum_{j=1}^i[\gcd(i,j)=1]-1\right) S=pni=1pnj=1pn[gcd(i,j)=1]=pn(2i=1pnj=1i[gcd(i,j)=1]1)

这个 − 1 -1 1是因为不能让 ( p , p ) (p,p) (p,p)统计两次,根据 φ \varphi φ的定义,会发现原式等价于 ∑ 质 数 p ∣ n ( 2 ∑ i = 1 ⌊ n p ⌋ φ ( i ) − 1 ) \sum_{质数p|n}\left(2\sum_{i=1}^{\lfloor\frac{n}{p}\rfloor}\varphi(i)-1\right) pn(2i=1pnφ(i)1)

预处理欧拉函数前缀和即可线性求解

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define N 10000005
#define int long long
int n, phi[N], prime[N], v[N], cnt, s[N];
int init() {
	phi[1] = 1;
	scanf("%lld", &n);
	for (int i = 2; i <= n; i++) {
		if (!v[i]) {
			v[i] = i;
			prime[++cnt] = i;
			phi[i] = i - 1;
		}
		for (int j = 1; j <= cnt; j++) {
			if (prime[j] > v[i] || prime[j] * i > n)break;
			v[prime[j] * i] = prime[j];
			phi[prime[j] * i] = i % prime[j] ? phi[i] * (prime[j] - 1) : phi[i] * prime[j];
		}
	}
	for (int i = 1; i <= n; i++) {
		s[i] = s[i - 1] + phi[i];
	}
	return 0;
}
void solve() {
	int m = n, ans = 0;
	for (int i = 1; i <= cnt; i++) {
		ans += s[m / prime[i]] << 1;
		ans--;
	}
	printf("%lld", ans);
	return;
}
signed main() {
	init();
	solve();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值