【题解】[SDOI2012] Longge 的问题

题目信息

题目来源:CCF 山东省选 2012;

在线评测地址:Luogu#2303

运行限制:时间不超过 (3.00 extrm{s}),空间不超过 (128 extrm{MiB})

题目背景

Longge 的数学成绩非常好,并且他非常乐于挑战高难度的数学问题。

题目描述

现在问题来了:给定一个整数 (n),你需要求出 (sumlimits_{i=1}^n gcd(i,n)),其中 (gcd(i,n)) 表示 (i)(n) 的最大公因数。

输入格式

输入只有一行一个整数,表示 (n)

输出格式

输出一行一个整数表示答案。

数据规模与约定

  • 对于 (60\%) 的数据,保证 (nle 2^{16})
  • 对于 (100\%) 的数据,保证 (1le nle 2^{32})

分析

这道题太经典了,以至于后面的很多数论题都是模仿这个形式的。

(60 exttt{pts})

暴力求即可,复杂度 (mathcal{O}(nlog n))

(100 exttt{pts})

我们要推一下式子,来优化这个算法。

[egin{aligned} sumlimits_{i=1}^n gcd(i,n)=&sumlimits_{i=1}^n sumlimits_{d|n}dleft[[d|i]landleft[gcdleft(frac{i}{d},frac{n}{d} ight)=1 ight] ight]\ =&sumlimits_{d|n}dsumlimits_{d|i}left[gcdleft(frac{i}{d},frac{n}{d} ight)=1 ight]\ =&sumlimits_{d|n}dvarphileft(frac{n}{d} ight) end{aligned} ]

枚举所有因数,计算即可,复杂度 (mathcal{O}(sigma(n)sqrt{n})),可以 AC。

Bonus

当然,这道题这么数学,其实有更好的做法,可以做到 (mathcal{O}(sqrt{n})) 的优秀复杂度。

具体内容可以看这一篇文章。

注意事项

这道题非常细节,很容易不知不觉就 WA、TLE。

边界问题

看到那个数据范围 (le 2^{32}) 没有?(n) 是可以等于 (2^{32}) 的,所以别忘了开 long long

当然所有中间变量都得开 long long,否则会出现溢出。

同时,判定质数时注意平方数情况。

特判问题

(varphi(n)) 时,得先判质数,然后进行质因数分解。

同时,质因数分解时循环也只能开到 (sqrt{n}) 级别,最后还要特判是否有没有除掉的数。否则一个 (2 imes (2^{31}-1)) 就能卡得飞起。

还有,你有没有把 (1) 判为质数呢?特判一定要加!

Code

经过了,这道题终于 (color{GreenYellow}{ exttt{AC}}) 了。

#include <cstdio>
using namespace std;

typedef long long ll;

ll phi(ll x) // 计算
{
	ll ans = 1;
	bool flag = false;

	for (ll i = 2; i * i <= x; i++) // 判质数
		if (!(x % i))
		{
			flag = true;
			break;
		}
	
	if (!flag && x != 1) // 是质数
		return x - 1; // 退出

	for (ll i = 2; i * i <= x; i++) // 否则就开始找质因数
		if (!(x % i)) // 找到了
		{
			ans *= (i - 1), x /= i; // 计算贡献
			while (!(x % i))
				x /= i, ans *= i;
		}
	
	if (x != 1) // 还没算干净,一定是质数
		ans *= x - 1; // 直接计算贡献
	
	return ans; // 返回答案
}

int main()
{
	ll n, ans = 0;

	scanf("%lld", &n); // 输入
	for (ll i = 1; i * i <= n; i++) // 筛因数
		if (!(n % i)) // 找到了(一对)
		{
			ans += phi(i) * (n / i); // 计算一个
			if (i * i < n) // 不是平方数
				ans += phi(n / i) * i; // 就再计算一个。
		}
	
	printf("%lld
", ans); // 输出

	return 0; // 然后就 AC 了、
}
原文地址:https://www.cnblogs.com/5ab-juruo/p/solution-sdoi2012_lg2303.html