1. 程式人生 > >【51Nod 1040】 最大公約數之和

【51Nod 1040】 最大公約數之和

Description

這裡寫圖片描述

Solution

分析題目可以發現,兩個數gcd(a,b)=x,則等價於gcd(ax,bx)=1,問題就可以轉化為滿足gcd(nx,ix)=1的i的個數,對答案貢獻就是個數乘上gcd(n,i)。很容易可以想到尤拉函式,因為φ(n)是小於等於n的數中與n互質的數的數目,gcd(nx,ix)=1的i的個數就等於φ(nx),那麼x用n的時間列舉就好了。

Code

var
    p:array[0..50000] of boolean;
    s:array[0..50000] of longint;
    n,i,j,sum:longint;
    ans:int64;
    pd:boolean;
procedure
deal;
var i,j,maxn:longint; begin maxn:=trunc(sqrt(n)); for i:=2 to maxn do begin if p[i]=false then begin inc(s[0]);s[s[0]]:=i;p[i]:=true; end; for j:=1 to s[0] do begin if i*s[j]>maxn then break; p[i*s[j]]:=true
; if i mod s[j]=0 then break; end; end; end; function phi(sum:longint):int64; begin phi:=1; for j:=1 to s[0] do begin if sum<s[j] then break; pd:=false; while sum mod s[j]=0 do begin sum:=sum div s[j]; if
pd then phi:=phi*s[j] else phi:=phi*(s[j]-1); pd:=true; end; end; if sum>1 then phi:=phi*(sum-1); end; begin readln(n); deal; for i:=1 to trunc(sqrt(n)) do if n mod i=0 then begin sum:=n div i; ans:=ans+i*phi(sum); if i<>sum then ans:=ans+sum*phi(i) end; writeln(ans); end.