zoukankan      html  css  js  c++  java
  • 【POJ2480】Longge's problem

    题目链接

    Longge's problem

    题目描述

    Longge is good at mathematics and he likes to think about hard mathematical problems which will be solved by some graceful algorithms. Now a problem comes: Given an integer (N)((1 < N < 2^{31})),you are to calculate (sum gcd)((i, N)) (1 le i le N).

    "Oh, I know, I know!" Longge shouts! But do you know? Please solve it.

    输入格式

    Input contain several test case.
    A number (N) per line.

    输出格式

    For each (N), output ,(sum gcd)((i,N)) (1 le i le N), a line

    样例输入

    2
    6
    

    样例输出

    3
    15
    

    题解

    题目要求(sum_{i=1}^ngcd)((i,n))
    那么我们考虑一个数(i)对答案的贡献,也就是(gcd)((k,n))(==i)的个数乘上(i)
    首先,如果(i)不是(n)的因数,那么不可能有(gcd)((k,n))(==i),所以(i)对答案的贡献为(0)
    那么如果(i)(n)的因子,那么如果存在(gcd)((k,n))(==i),那么(k)一定满足(k/i)(n/i)互质,也就是说(k)(n)的因子中除去(i)后没有相同的因子了。
    那么我们马上就发现了(i)对答案的贡献就是(i*phi)((n/i))。
    那么显然题目就变成了求(sum_{i|n}i*phi)((n/i))

    在判断质数的时候我们都学过一个数的因子都是“对称”的,所以在枚举(phi)((n/i))的过程中我们只要枚举到(sqrt{n}),就行了。

    接下来的目标就是如何快速求(phi)((i))了,
    我们先了解欧拉函数的一些性质:
    有一个质数(p),则
    (phi)((p^k))(=p^k-p^{k-1}=p^{k-1}*(p-1))
    因为(p^k)以内不和(p^k)互质的数只有(p)的倍数,也就是数量为(frac{p^k}{p})
    因为(phi)是积性函数,所以令(p,k)互质,则
    (phi)((p*k))(=phi)((p))(*phi)((k))
    所以我们就能用下面的代码求(phi)

    inline long long phi(long long x){
        long long sum=x;
        for(long long j=2;j*j<=x;j++)
            if(x%j==0){
                while(x%j==0) x/=j;
                sum=sum/j*(j-1);
            }
        if(x!=1) sum=sum/x*(x-1);
        return sum;
    }
    

    ps:有多组数据
    上代码:

    #include<cstdio>
    using namespace std;
    long long n;
    inline long long fd(long long x){
        long long sum=x;
        for(long long j=2;j*j<=x;j++){
            if(x%j==0){
                while(x%j==0) x/=j;
                sum=sum/j*(j-1);
            }
        }
        if(x!=1) sum=sum/x*(x-1);
        return sum;
    }
    long long sum;
    int main(){
        while(scanf("%lld",&n)!=EOF){
            sum=0;
            for(long long i=1;i*i<=n;i++){
                if(n%i==0) sum+=fd(n/i)*i;
                long long u=n/i;
                if(u!=i && n%u==0) sum+=fd(n/u)*u;
            }
            printf("%lld
    ",sum);
        }
        return 0;
    }
    
  • 相关阅读:
    实习小白::(转) Cocos2d-x 3.0开发(五)关联程序逻辑与cocoStudio导出文件
    实习小白::(转)Cocos2d-x 3.0开发(六)使用cocoStudio创建一个骨骼动画
    实习小白::(转) Cocos2d-x 3.0 开发(七)在程序中处理cocoStudio导出动画
    实习小白::(转) cocos2d-x使用cocosStudio编辑的动画文件
    (转)cocos2d-x 每帧动画的播放设置一个监听函数的做法
    Filter
    使用Cookie记住用户名和密码
    动态规划
    热分布
    背包问题
  • 原文地址:https://www.cnblogs.com/linjiale/p/13477819.html
Copyright © 2011-2022 走看看