上链接:
P2303 [SDOI2012] Longge 的问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P2303
大致题意:
求
这道题和洛谷P2568有异曲同工之妙:
由于gcd(i,n)必然是n的一个因子,而 必然取遍了n的所有因子。
设 gcd(i,n) = d ,那么 i= x*d,所以 x 必然和 n/d 互质 。
当d固定的时候,i可以为多个答案,也就代表 x可以是多个答案。
可知 x 必然能取遍1~n/d 的所有与 n/d的互质的数。有多少个x呢?也就是.
对于 一个 n/d 我们的答案是
所以我们只需要求出n的所有的因数的欧拉函数乘该因数本身 再累加即可
也就是:
tot代表的就是 n的因数的个数。
所以我们第一步就是先把n的所有因子找出来放进一个数组里。
第二步对于每个因数d求出 n/d的欧拉函数用d*,
或者
对于每个因数d求出d 的欧拉函数,再用 n/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;
}