51nod1040&poj 2480(欧拉函数-最大公约数)1-n同n的最大公约数之和

题目

给出一个n,求1-n这n个整数,同n的最大公约数的和。比如:n = 6; 1,2,3,4,5,6 同6的最大公约数分别为1,2,3,2,1,6,加在一起 = 15。

输入

1个整数N(N <= 10^9)

输出

公约数之和

分析

题意很明确,求同n的最大公约数的和。如果n的范围很小,小至10^6,那么这就是一道数学题,但是n的范围很大,所以这就是一个数论题了。先来看一下当n=6时,结果15是咋来的,n=6时,1与6的最大公约数是1;2与6的最大公约数是2;3与6的最大公约数是3;4与6的最大公约数是2;5与6的最大公约数是1;6与6的最大公约数是6;那么用一个num数组来存就是num[6] = {1,2,3,2,1,6};其中1出现2次,2出现了2次,3出现1次,6出现1次。此时我们就惊奇的发现,1、2、3、6都是6的因子。用数组divisor[4] = {1,2,3,6};来表示6的因子。用cnt[4] = {2,2,1,1};来表示因子出现的次数。那么为什么1的时候出现2次、2出现了2次,3出现1次,6出现1次呢?其实这里就用到了数论里边的欧拉函数的知识,如果一个数i与6的最大公约数是1,那么i/1与6/1必然是互质的(因为两个数p和q的最大公约数是k,那么p/k与q/k互质)。那么此时只需求出6/1的欧拉数便是6与i最大公约数是1的数。6/1的欧拉数的项的数分别是1和5两个数,那么6与i的最大公约数是1的数分别是1×1和1×5。所以cnt[0] = 2;同理,例如一个数i与6的最大公约数是2时,i/2与6/2必然是互质的。6/2的欧拉数的项的数分别是1和2两个数。那么6和i的最大公约数是2的数分别是2×1和2×2,既是2和4;同理最大公约数为3的数是3×1、最大公约数为6的数是6×1,所以cnt数组的内容是{2,2,1,2}。

以上是详细过程,下面是简单过程。
先找出n的因子,假设为x,如果一个数i与n的最大公约数是x,那么必定 i/x 与 n/x 互质,既是gcd( i / x , n / x) = 1,看到这个式子可以想到欧拉函数,也就是求比n/x小的与其互质的个数。然后因子*(n/x的欧拉数)求和即可。

代码如下

#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
ll euler(ll x)
{
    ll res = x;
    for(int i = 2; i*i <=x; i++)
    {
        if(x%i==0)
        {
            res = res/i*(i-1);
            while(x%i==0)
                x/=i;
        }
    }
    if(x>1)
        res = res/x*(x-1);
    return res;
}
int main()
{
    ll n, sum = 0;
    scanf("%lld", &n);
    ll k = sqrt(n);
    for(int i = 1; i <= k; i++)
    {
        if(n%i == 0)
        {
            sum += i*euler(n/i);     //因子i*(n/i的欧拉数)
            if(i*i!=n)
                sum += n/i*euler(i);
        }
    }
    printf("%lld", sum);
    return 0;
}

发布了27 篇原创文章 · 获赞 13 · 访问量 1717

猜你喜欢

转载自blog.csdn.net/weixin_43855330/article/details/85771784