1. 程式人生 > >hdu2588(尤拉函式的運用)

hdu2588(尤拉函式的運用)

Problem Description

The greatest common divisor GCD(a,b) of two positive integers a and b,sometimes written (a,b),is the largest divisor common to a and b,For example,(1,2)=1,(12,18)=6.
(a,b) can be easily found by the Euclidean algorithm. Now Carp is considering a little more difficult problem:
Given integers N and M, how many integer X satisfies 1<=X<=N and (X,N)>=M.

題意:給定n,m,求在1~n之間有多少個數,也就是x,gcd(x,n)>=m

解題思路:n的範圍很大,不能列舉1~n,好像與gcd有關的題都要用到尤拉函式。。。

所以換個思路,假如n的一個因子fac>=m,則設n=fac*k,原式就變為gcd(x,fac*k)>=m,如何才能滿足這個式子呢?

當然要x與k互質,當gcd(x,k)==1時(也就是互質),gcd(x,fac*k)==fac>=m,成立!

所以我們就要找與k互質的數的個數,也就是n/fac的尤拉函式值,最後處理一下fac和k相等的情況即可

#include <bits/stdc++.h>

using namespace std;

int Euler(int n)
{
    int num=n;
    for(int i=2; i<=sqrt(n); i++)
        if(n%i==0)
        {
            num=num/i*(i-1);//先進行除法防止溢位(num=num*(1-1/p(i)))
            while(n%i==0)
                n/=i;
        }
    if(n>1)
        num=num/n*(n-1);
    return num;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int m,n,ans;
        ans=0;
        cin>>n>>m;
        for(int i=1; i<=sqrt(n); i++)
        {
            if(n%i==0)//列舉每一個因子
            {
                if(n/i>=m && i!=(n/i))//fac[i]==i的話就計算了兩次
                    ans+=Euler(i);
                if(i>=m)
                    ans+=Euler(n/i);
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}