您的位置:首页 > 其它

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

2015-03-27 23:24 423 查看
给出一个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 long
using 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: