转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
http://poj.org/problem?id=2480
给出N,求∑gcd(i, N) 1<=i <=N.
推导太犀利了。
首先对于每一个N的因子d,如果gcd(m,n)=d,那我们需要找出有多少这样的m,其实这步比较简单就是d*phi(n/d)。
也许会想,为什么不是n/.d个呢,应该有n/d个都是d的倍数,拥有d这个因子。考虑如果与n/d不互质的一个数乘以d,和n的最大公约数必定不是d,那么就会重复计算,欧拉函数的神奇应用。
由于N比较大,也不适合枚举所有因子,也许打出素数表加上快速求eular可以水过。
先要了解eular函数的一个性质。
phi(p^k)=(p-1)*p^(k-1)
考虑如果N=P^k的时候,那么F[N]=p*phi(p^k-1)=k*p^(k-1)+p^k。
利用eular的积性性质
F[N]=F[p1^k1*p2^k2……pi^ki]=∑(ki*pi^(ki-1)+p^ki).
接下来对于N进行因式分解。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define LL long long
#define MOD 1000000007
using namespace std;
int main(){
LL n;
while(scanf("%lld",&n)!=EOF){
LL ans=1;
for(LL i=2;i*i<=n;i++)
if(n%i==0){
LL k=0,p=1;
while(n%i==0){
k++;
p*=i;
n/=i;
}
ans*=k*(p-p/i)+p;
}
if(n>1)
ans*=2*n-1;
printf("%lld\n",ans);
}
return 0;
}