【51NOD】 1040-最大公约数之和(欧拉函数)

原题连接

首先补充一个知识点,欧拉函数:

在数论,对正整数n,欧拉函数是小于n的正整数中与n互质的数的数目(φ(1)=1)。此函数以其首名研究者欧拉命名(Euler’s totient function),它又称为Euler’s totient function、φ函数、欧拉商数等。 例如φ(8)=4,因为1,3,5,7均和8互质。

c语言实现:

int eular(int n)
{
    int ret=1,i;
    for(i=2;i*i<=n;i++)
    {
        if(n%i==0)
        {
            n/=i,ret*=i-1;
            while(n%i==0) n/=i,ret*=i;
        }
    }
    if(n>1) ret*=n-1;
    return ret;
}

性质:

参见
这是一个比较详细的解释了。

解题思路:

既然是1~n与n的公约数,那么肯定是n的因子。对于每一个n的因子x对sum产生的增量为:gcd(n, i) = x的个数,也就是gcd(n / x, i / x) = 1的个数乘以x,这时,顺理成章的也就想起了phi(n / x)了。

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

ll euler(ll n){
    ll i,m = (int)sqrt(n + 0.5),ans = n;
    for(i = 2 ; i <= m ; i++){
        if(n%i==0){
            ans = ans/i*(i-1);
            while(n%i==0)   n /= i;
        }
    }
    if(n>1) ans = ans/n*(n-1);
    return ans;
}
int main(void){
    ll x,sum = 0;
    cin>>x;
    for(ll i = 1;i*i <= x;i++){
        if(x%i!=0)  continue;
        ll t = x/i;
        sum += i*euler(t);
        if(i != t)  sum += t*euler(i);
    }
    cout<<sum<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41009682/article/details/81120442