1. 程式人生 > >POJ2480 Longge's problem【乘性函式】

POJ2480 Longge's problem【乘性函式】

題目連結:

題目大意:

給一個正整數n,求Σgcd(i,n),(1 <= i <= n)。

思路:

如果m,n互質,則gcd(i,m*n) = gcd(i,m) * gcd(i,n),所以gcd是乘性函式。

因為乘性函式的和函式也是乘性函式,所以Σgcd(i,N)也是乘性函式。

首先考慮gcd(x,n) = 1,這樣的數和剛好為尤拉函式之和sum( φ(n)),現在考慮gcd(x,n) = p

的情況,因為gcd(x/p,n/p) = 1,就變成了尤拉函式之和sum(φ(n/p)),所以gcd(x,n) = p,這種

情況下結果為sum( p*phi(n/p) ),p為n的約數。總結就是Σgcd(i,N) = Σp*phi(n/p),p是n的約數。

Σp*phi(n/p) = H(n),因為H(n)為乘性函式,H(n) = H(p1^k1) * H(p2^k2) * … * H(pn^kn),

對於素數p^k,有:φ(p^k) = p^k - p^(k-1),

所以H(pi^ki) = p^k - p^(k-1) + p*(p^(k-1) - p^(k-2)) + p^2*(p^(k-2) - p^(k-3)) + ……

                     = p^k + k*(p^k - p^(k-1) )

那麼解題步驟為將N分解素因子,對每個素因子計算H(pi^ki),最後加起來。

AC程式碼:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;

int main()
{
    __int64 n,i,N,a,p,ans;
    while(~scanf("%I64d",&n))
    {
        N = n;
        ans = n;
        for(i = 2; i*i <= N; ++i)
        {
            if(n % i == 0)
            {
                a = 0;
                p = i;
                while(n % p == 0)
                {
                    a++;
                    n /= p;
                }
                ans += ans*a*(p-1)/p;
            }
        }
        if(n != 1)
            ans += ans*(n-1)/n;

        printf("%I64d\n",ans);
    }

    return 0;
}