《深入浅出进阶篇》p2303Longge ——欧拉函数的运用

上链接:

P2303 [SDOI2012] Longge 的问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)icon-default.png?t=N7T8https://www.luogu.com.cn/problem/P2303

大致题意:

\sum_{i=1}^{n}gcd(i,n)

这道题和洛谷P2568有异曲同工之妙:

《洛谷深入浅出进阶篇》p2568 GCD-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/louisdlee/article/details/134886352?spm=1001.2014.3001.5502

 由于gcd(i,n)必然是n的一个因子,而 \sum_{i=1}^{n}gcd(i,n)必然取遍了n的所有因子。

设 gcd(i,n) = d ,那么  i= x*d,所以 x 必然和  n/d 互质  。

当d固定的时候,i可以为多个答案,也就代表 x可以是多个答案。

可知  x 必然能取遍1~n/d 的所有与 n/d的互质的数。有多少个x呢?也就是\psi(\frac{n}{d}).

对于 一个 n/d   我们的答案是  \psi(\frac{n}{d})*d

所以我们只需要求出n的所有的因数的欧拉函数乘该因数本身 再累加即可

也就是:

\sum_{i=1}^{tot}\psi(\frac{n}{d_{i}})*d_{i}

tot代表的就是 n的因数的个数。

所以我们第一步就是先把n的所有因子找出来放进一个数组里。

第二步对于每个因数d求出 n/d的欧拉函数用d*\psi(\frac{n}{d})

或者

对于每个因数d求出d 的欧拉函数,再用 n/d * \psi({d})

(第二种比较方便。)

这里特别说一下传统的求欧拉函数是从2开始列举到n。

但是你已经把n以内的所有因数求出来了就不需要这么麻烦。

为什么?

因为我们要求的是d这个数的每个质因子。

而d的因子必然是n的因子,所以我们只需要从n的因子表中列举n的因子表

就可以了,这样可以减少很多时间。

第三步 累加每一个答案。

上代码:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<cctype>
#include<map>
#include<set>
#include<queue>
#include<numeric>
#include<iomanip>


using namespace std;
const int N = 5e3;
int d[N];
int main() {
	int n;
	cin >> n;
	int tot = 0;
	for (int i = 1; i <= n / i; i++) {
		if (n % i == 0) {
			d[++tot] = i;
			if (i != n / i)
				d[++tot] = n / i;
		}
	}
	sort(d + 1, d + 1 + tot);
	long long phi = 0,tmp=0;
	long long ans = 0;
	for (int i = 1; i <= tot; i++) {
		phi = tmp = d[i];
		for (int j = 2;j<=i and d[j] * d[j] <= tmp; j++) {
			if (tmp % d[j] == 0) {
				phi = phi / d[j] * (d[j] - 1);
				while (tmp % d[j] == 0)tmp /= d[j];
			}
		}
		if (tmp != 1)phi = phi / tmp * (tmp - 1);
		ans += n / d[i] * phi;
	}
	cout << ans;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

louisdlee.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值