1. 程式人生 > >【51NOD】 1040-最大公約數之和(尤拉函式)

【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; }