1. 程式人生 > >[51nod1040]最大公約數之和

[51nod1040]最大公約數之和

Description

i=1ngcd(i,n)
n<=10^9

Solution

這道題有多種做法。
我們設f(n)=ni=1gcd(i,n)
那麼f應該是積性函式。(證明自行腦補)
也就是說我們要求出來f(pk)p
直接推式子似乎很麻煩,我們換個思路。
如何從f(pk)轉移到f(pk+1)?
首先,因為我們可以把f(p^k)*p,那麼就構成了f(p^k+1)的答案中所有不為1的部分.
(顯然gcd(i,p)=gcd(ip,p2)p
那麼剩下的為1的就是φ(pk+1)了。
於是我們得到了

f(pk+1)=f(pk)p+φ(pk+1)
於是就解決了。

然而,我發現似乎只有我一個人想用積性函式的方法。
其餘的都是機智的直接φ

法。
因為我們的答案都是n的因數。那麼我們把它分解質因數,列舉每個因數x,我們就是要求1~n有多少個數k滿足gcd(x,k)=x很顯然有φ(nx)個。
於是暴力求φ也可以。

Code

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long ll;
ll ans;
int a[32],b[32
],n; int main() { scanf("%d",&n);int i=2;ans=1; fo(i,2,sqrt(n)) { if (!(n%i)) a[++a[0]]=i; while (!(n%i)) b[a[0]]++,n/=i; } if (n>1) a[++a[0]]=n,b[a[0]]=1; fo(i,1,a[0]) { ll sum=1,x=1; fo(j,1,b[i]) sum=sum*a[i]+x*(a[i]-1),x*=a[i]; ans*=sum; } printf
("%lld",ans); }