#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define INF 0x3f3f3f3f
#define rep0(i, n) for (int i = 0; i < n; i++)
#define rep1(i, n) for (int i = 1; i <= n; i++)
#define rep_0(i, n) for (int i = n - 1; i >= 0; i--)
#define rep_1(i, n) for (int i = n; i > 0; i--)
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define mem(x, y) memset(x, y, sizeof(x))
/**
题目大意
求 1 ~ n 范围内所有数i与n的gcd的和
思路
i = a * b
n = a * d
且 gcd(b, d) = 1
gcd(i, n) = a
题目可转换为与n的gcd为a的i的个数 <=> b的个数(b <= d and gcd(b, d) = 1)
即 ans += a * euler(d)
于是枚举n的因数(折半枚举)
*/
using namespace std;
typedef long long LL;
LL euler(LL n)
{
LL res = n, a = n;
for (LL i = 2; i * i <= a; i++)
{
if (a % i == 0)
{
res = res / i * (i - 1);
while (a % i == 0)
{
a /= i;
}
}
}
if (a > 1)
res = res / a * (a - 1);
return res;
}
LL solve(LL n)
{
LL ans = 0;
for (LL i = 1; i * i <= n; i++)
{
if (n % i)
continue;
ans += euler(i) * n / i;
if (i * i != n)
ans += euler(n / i) * i;
}
return ans;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif // ONLINE_JUDGE
LL n;
while (scanf("%lld", &n) != EOF)
printf("%lld\n", solve(n));
return 0;
}
POJ2480_Longge's problem(欧拉函数)
最新推荐文章于 2019-10-04 14:47:07 发布
本文介绍了一种高效的算法来求解1到n范围内所有数i与n的最大公约数(GCD)之和。通过枚举n的因数并利用欧拉函数计算与n的GCD为特定值的数的数量。
620

被折叠的 条评论
为什么被折叠?



