51nod 1040 最大公约数之和 (数学)

来源:互联网 发布:mac查看php安装目录 编辑:程序博客网 时间:2024/05/23 18:44

给出一个n,求1-n这n个数,同n的最大公约数的和。比如:n = 6
1,2,3,4,5,6 同6的最大公约数分别为1,2,3,2,1,6,加在一起 = 15
Input

1个数N(N <= 10^9)

OutPut

公约数之和

Input示例

6

Output示例

15

分析:
因子i的个数k=Phi(n/i),请看例子n=12
1~n: 1 2 3 4 5 6 7 8 9 10 11 12
最大公约数:1 2 3 4 1 6 1 4 3 2 1 12
首先看1,共有4个1,分别是1 5 7 11 :12(n),很明显这4个数是与12互素的数,即Phi(12),Phi:是欧拉函数。
看2:共有2个2,分别是
2–>2 10 :12同时除以2得
1–>1 5 :6(12/2),此时1,5是与6互素的数,个数为Phi(6)=Phi(12/2);
同理可以退出其他,对已i的个数为K=Phi(n/i)。

AC代码:

/**  *@xiaoran  *1    2   3   4   5   6  *1    2   3   2   1   6  *2个1,2个2,1个3,1个6,注意后面的值都是n的因子。  *现在我们只需要计算出各个因子的个数就行了,  *那么1的个数是与n互质的个数,即欧拉函数的值  *2的个数k=Phi(n/2),  *对于n的因子i的个数k=Phi(n/i),sum+=k*i,  */#include<iostream>#include<cstdio>#include<map>#include<cstring>#include<string>#include<algorithm>#include<queue>#include<vector>#include<stack>#include<cstdlib>#include<cctype>#include<cmath>#include<ctime>#define LOCAL#define LL long longusing namespace std;LL Phi(int n){//求欧拉函数    if(n==1) return 1;    LL ans=n;    int k=(int) sqrt(n+0.5);    for(int i=2;i<=k;i++){        if(n%i==0){            ans=ans*(i-1)/i;        }        while(n%i==0) n/=i;    }    if(n>1) ans=ans*(n-1)/n;    return ans;}int gcd(int a,int b){    int r;    if(b==0) return a;    while(b){        r=a%b;        a=b;        b=r;    }    return a;}int PK(int k,int n){    int s=1;    for(int i=k*2;i<n;i+=k){//计算k的个数        if(gcd(n,i)>k) continue;        s++;    }    return s;}int main(){    /*    #ifdef LOCAL        freopen("input.txt","r",stdin);        freopen("output.txt","w",stdout);    #endif    */    int n;    while(cin>>n){        LL t1=clock();        int k=(int) sqrt(n+0.5);        LL ans=n;        for(int i=2;i<=k;i++){            if(n%i==0){                //cout<<PK(i,n)<<" "<<PK(n/i,n)<<endl;                ans+=Phi(n/i)*i+(n/i)*Phi(i);            }        }        ans+=Phi(n);        if(k*k==n){            ans-=k*Phi(k);        }        cout<<ans<<endl;        LL t2=clock();        //cout<<t2-t1<<endl;    }    return 0;}
0 0
原创粉丝点击