POJ2480_Longge's problem(欧拉函数)

本文介绍了一种高效的算法来求解1到n范围内所有数i与n的最大公约数(GCD)之和。通过枚举n的因数并利用欧拉函数计算与n的GCD为特定值的数的数量。
#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值