题目链接:http://poj.org/problem?id=2480
大意:给出正整数n,求sum=gcd(1,n)+gcd(2,n)+...+gcd(n,n)是多少
n的范围是2^31,直接算肯定超时
若gcd(i,n)=k,k一定是n的约数,那么可知gcd(i/k,n/k)=1,即求i/k与n/k互质的i有多少个,那么个数就是欧拉函数φ(n/k),那么总共就是k*φ(n/k),由此可知f(n)=∑k*φ(n/k),k为n的约数,由于n过大,所以可以只计算到sqrt(n),而大于sqrt(n)的部分当i=n/k,其值为n/k*φ(k),那么只需要在i=k的时候加上即可。
#include <iostream>
#include<cmath>
#include<cstdio>
using namespace std;
typedef long long ll;
ll euler(int x){
int res=x;
for(int i=2;i<=sqrt(x);i++){
if(x%i==0){
res=res/i*(i-1);
while(x%i==0){
x/=i;
}
}
}
if(x>1)
res=res/x*(x-1);
return res;
}
int main()
{
ll n,ans,i;
while(cin>>n){
ans=0;
for(i=1;i<sqrt(n);i++){//由于数据范围大用sqrt缩小数据
if(n%i==0){
ans+=i*euler(n/i)+n/i*euler(i);
}
}
if(i*i==n){//如果i=sqrt(n),那么只需要计算一次
ans+=i*euler(n/i);
}
cout<<ans<<endl;
}
return 0;
}