1. 程式人生 > >hdu3501 給出一個N,求1..N中與N互質的數的和

hdu3501 給出一個N,求1..N中與N互質的數的和

給出一個N,求1..N中與N互質的數的和

ifgcd(n,i)=1 then gcd(n,n-i)=1 (1<=i<=n)

反證法:

        如果存在K!=1使gcd(n,n-i)=k,那麼(n-i)%k==0

        而n%k=0

        那麼必須保證i%k=0

        k是n的因子,如果i%k=0那麼 gcd(n,i)=k,矛盾出現;

        於是問題變的非常簡單: ANS=N*phi(N)/2

        i,n-i總是成對出現,並且和是n

       於是可能就有人問了,如果存在n-i=i那不是重複計算?

        答案是不會

        因為:

                n=2*i->i=n/2

1.如果n是奇數,那麼n!=2*i,自然也不存在 n-i=i和重複計算之說

2.如果n是偶數,n=2*i成立,gcd(n,n/2)必然為n的一個因子,這個因子為1當且僅當n==2

3.於是對於n>2的偶數,絕對不存在gcd(n,n/2)=1所以更別說什麼重複計算了

        對於n==2

        ans=2*1/2=1,正好也滿足

        所以得到最終公式:

                  ans=N*phi(N)/2 

#include<iostream>
#include<cmath>
using namespace std;
const int MM=1000000007;
__int64 euler(__int64 x)
{
        __int64 i,res=x;
        for(i=2;i<(__int64)sqrt(x*1.0)+1;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()
{
    __int64 n,sum,ans;
    while(scanf("%I64d",&n)!=EOF && n)
    {
         sum=n*(n+1)/2-n;
         ans=sum-euler(n)*n/2;
         printf("%I64d\n",ans%MM);
    }
    return 0;
}