【51NOD】 1040-最大公約數之和(尤拉函式)
阿新 • • 發佈:2019-01-22
首先補充一個知識點,尤拉函式:
在數論,對正整數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;
}