POJ 2480 Longge's problem

题目链接: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;
}

猜你喜欢

转载自blog.csdn.net/qq_38802708/article/details/81428184
今日推荐