51nod 1040 最大公约数之和

来源:互联网 发布:mac svn客户端 编辑:程序博客网 时间:2024/05/29 05:03

51nod 1040 最大公约数之和

这里写图片描述

解法一 欧拉函数:

由题意得,该题求Σ(n,i=1)gcd(i,n)令gcd(i,n)=x,枚举n的因子x,最后答案为因子x乘以x出现的次数的和。求gcd(n,i)=x出现的次数,即gcd(n/x,i/x)=1的个数,就是求φ(n/x)。

这里写图片描述
公式一:

#include<iostream>#include<cmath>#include<algorithm>#include<cstring>using namespace std;int m;long long euler(int n)  //公式一{    long long ans=n;    for(int i=2;i*i<=n;i++)    {        if(n%i==0)        {            ans-=ans/i;            while(n%i==0)                n=n/i;        }    }    if(n>1) ans-=ans/n;    return ans;}int main(){    int n;    cin>>n;    long long ans=0;    m=sqrt(n);    for(int i=1;i<=m;i++)    {        if(n%i==0)        {           ans+=i*euler(n/i);           if(i*i!=n) ans+=(n/i)*euler(i);         }    }    cout<<ans<<endl;    //system("pause");    return 0;}  

*

*

解法二 暴力 筛重:

找出所有约数,排序,筛重。

#include<iostream>#include<cmath>#include<algorithm>#include<cstring>using namespace std;int a[4000],b[4000];int main(){    int n;    cin>>n;    int sum=0;    int m=sqrt(n);    for(int i=1;i<=m;i++)    {        if(n%i==0)        {           a[sum++]=i;           if(n!=m*m) a[sum++]=n/i;         }    }    sort(a,a+sum);    long long ans=0;    for(int i=sum-1;i>=0;i--)    {        b[i]=n/a[i];            for(int j=i+1;j<sum;j++)        {          if(a[j]%a[i]==0) b[i]-=b[j];  //(1)        }       ans+=a[i]*b[i];           }     cout<<ans<<endl;    // system("pause");     return 0;} 

(1) 若n=20,当前处理的约数为2,即a[i]=2。b[i]=20/2=10,说明20里面有10个数字是2的倍数,但这题求的是最大公约数。如当a[j]=4时,4与20的最大公约数为4。所以凡是有4为因子的,最大公约数不能是2,所以b[i]-=b[j]。
(2)10^9中最多约数的数是931170240,有1344个约数。

原创粉丝点击