洛谷 P2398 GCD SUM

【题目链接】

洛谷 P2398 GCD SUM

【题目考点】

1. 数论:欧拉函数

欧拉函数 ϕ ( x ) \phi(x) ϕ(x)表示小于等于 x x x的与 x x x互质的数的个数。

欧拉函数具有如下性质:
n = ∑ d ∣ n ϕ ( d ) n=\sum_{d|n}\phi(d) n=dnϕ(d),即正整数n等于n的所有约数的欧拉函数值的加和。

2. 线性筛:求1到n的欧拉函数值

已知:对于质数 p p p
如果 p ∣ x p \mid x px,则 ϕ ( p x ) = p ϕ ( x ) \phi(px)=p\phi(x) ϕ(px)=(x)
如果 p ∤ x p\nmid x px,则 ϕ ( p x ) = ( p − 1 ) ϕ ( x ) \phi(px)=(p-1)\phi(x) ϕ(px)=(p1)ϕ(x)

在线性筛求质数时,i是当前访问的数值,prime[j]是当前遍历到的质数,phi[i]表示欧拉函数 ϕ ( i ) \phi(i) ϕ(i)
当确定i*prime[j]的最小质因数为prime[j]时,判断
如果i%prime[j] == 0,则phi[i*prime[j]] = prime[j]*phi[i]
否则如果i%prime[j] != 0,则phi[i*prime[j]] = (prime[j]-1)*phi[i]
递推可以求出1到n的欧拉函数。

【解题思路】

本题求:
∑ i = 1 n ∑ j = 1 n gcd ⁡ ( i , j ) \sum_{i=1}^n \sum_{j=1}^n \gcd(i, j) i=1nj=1ngcd(i,j)
根据欧拉函数的性质 n = ∑ d ∣ n ϕ ( d ) n=\sum\limits_{d|n}\phi(d) n=dnϕ(d),有:
g c d ( i , j ) = ∑ d ∣ g c d ( i , j ) ϕ ( d ) gcd(i,j)=\sum\limits_{d|gcd(i,j)}\phi(d) gcd(i,j)=dgcd(i,j)ϕ(d)
已知: d ∣ a , d ∣ b d|a, d|b da,db等价于 d ∣ g c d ( a , b ) d|gcd(a,b) dgcd(a,b),即公约数整除最大公约数。
那么:
g c d ( i , j ) = ∑ d ∣ i , d ∣ j ϕ ( d ) gcd(i,j)=\sum\limits_{d|i, d|j}\phi(d) gcd(i,j)=di,djϕ(d)
∑ i = 1 n ∑ j = 1 n gcd ⁡ ( i , j ) = ∑ i = 1 n ∑ j = 1 n ∑ d ∣ i , d ∣ j ϕ ( d ) \sum\limits_{i=1}^n \sum\limits_{j=1}^n \gcd(i, j)=\sum\limits_{i=1}^n \sum\limits_{j=1}^n\sum\limits_{d|i, d|j}\phi(d) i=1nj=1ngcd(i,j)=i=1nj=1ndi,djϕ(d)

即: i 、 j i、j ij分别枚举区间 [ 1 , n ] [1,n] [1,n]的值,如果 d d d i i i j j j的公约数,那么对结果贡献为 ϕ ( d ) \phi(d) ϕ(d)
由于 i 、 j i、j ij能取到的最大值为 n n n,所以 i 、 j i、j ij的公约数小于等于 n n n,因此 i 、 j i、j ij的公约数 d d d的取值范围为 [ 1 , n ] [1,n] [1,n]
因此可以在 [ 1 , n ] [1,n] [1,n]范围内枚举 d d d的值,对于每个 d d d的取值考察其对结果的贡献。
只有当 d ∣ i , d ∣ j d|i, d|j di,dj,即 i i i d d d的倍数且 j j j d d d的倍数时,才有贡献 ϕ ( d ) \phi(d) ϕ(d)
i i i的取值范围为 [ 1 , n ] [1, n] [1,n],其中 d d d的倍数有 d , 2 d , . . . , ⌊ n d ⌋ d d, 2d, ..., \lfloor \frac{n}{d} \rfloor d d,2d,...,dnd,共有 ⌊ n d ⌋ \lfloor \frac{n}{d} \rfloor dn d d d的倍数。
j j j的取值范围为 [ 1 , n ] [1, n] [1,n],同样其中共有 ⌊ n d ⌋ \lfloor \frac{n}{d} \rfloor dn d d d的倍数。
i i i d d d的倍数的情况有 ⌊ n d ⌋ \lfloor \frac{n}{d} \rfloor dn种, j j j d d d的倍数的情况有 ⌊ n d ⌋ \lfloor \frac{n}{d} \rfloor dn种,根据乘法原理, i 、 j i、j ij同时取 d d d的倍数的情况有 ⌊ n d ⌋ 2 \lfloor \frac{n}{d} \rfloor^2 dn2种。
因此,当 i 、 j i、j ij的公约数为 d d d时,对结果的贡献为 ⌊ n d ⌋ 2 ϕ ( d ) \lfloor \frac{n}{d} \rfloor^2\phi(d) dn2ϕ(d)
因此: ∑ i = 1 n ∑ j = 1 n gcd ⁡ ( i , j ) = ∑ d = 1 n ⌊ n d ⌋ 2 ϕ ( d ) \sum_{i=1}^n \sum_{j=1}^n \gcd(i, j)=\sum\limits_{d=1}^n\lfloor \frac{n}{d} \rfloor^2\phi(d) i=1nj=1ngcd(i,j)=d=1ndn2ϕ(d)

[ 1 , n ] [1,n] [1,n]范围内枚举 d d d的值,将 ⌊ n d ⌋ 2 ϕ ( d ) \lfloor \frac{n}{d} \rfloor^2\phi(d) dn2ϕ(d)加和即为结果。

该计算过程需要用到1到n的欧拉函数值,可以使用线性筛预处理求出 ϕ ( 1 ) ∼ ϕ ( n ) \phi(1)\sim \phi(n) ϕ(1)ϕ(n)的值。
该算法时间复杂度为 O ( n ) O(n) O(n)

【题解代码】

#include <bits/stdc++.h>
using namespace std;
#define N 100005
bool isPrime[N];
int prime[N], pn, phi[N];
long long n, ans;
void eulerSeive(int n)
{
	memset(isPrime, 1, sizeof(isPrime));
	phi[1] = 1;
	for(int i = 2; i <= n; ++i)
	{
		if(isPrime[i])
		{
			prime[++pn] = i;
			phi[i] = i-1;
		}
		for(int j = 1; j <= pn && i*prime[j] <= n; ++j)
		{
			isPrime[i*prime[j]] = false;
			if(i%prime[j] == 0)
			{
				phi[i*prime[j]] = prime[j]*phi[i];
				break;
			}
			else
				phi[i*prime[j]] = (prime[j]-1)*phi[i];
		}
	}
}
int main()
{
	cin >> n;
	eulerSeive(n);
	for(int d = 1; d <= n; ++d) 
		ans += (n/d)*(n/d)*phi[d];	
	cout << ans;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值