【hdu2588】求[1-n]中和n的gcd大于m的数的个数(求欧拉函数值)

版权声明:转载请注明出处哦~ https://blog.csdn.net/Cassie_zkq/article/details/89503410

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=2588

思路


欧拉函数值\varphi (n)的意思是[1,n]中gcd(x,n)=1的x的个数,x\epsilon[1,n]

如果x\epsilon[1,n],且gcd(x,n)=k,令x=k*a,n=k*b,那么a与b互质

由x≤n可知a≤b,所以求a的个数相当于转化为求[1,b]中和b互质的数的个数,\varphi(b),即\varphi(n/k),其中k\epsilon[m+1,n]

注意:k必须是n的约数,这道题n过大,分一半求即可,O(√n)

代码


#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <ctype.h>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <sstream>
#define  maxn 10000
typedef long long ll;
const ll mod=1e9+7;
using namespace std;
ll euler(ll x)
{
    ll ans=x;
    for(ll i=2;i*i<=x;i++)
    {
        if(x%i==0)
        {
            ans=ans/i*(i-1);
            while(x%i==0) x/=i;
        }
    }
    if(x!=1) ans=ans/x*(x-1);
    return ans;
}
int main()
{
    //freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);
    ll n,m,t;
    cin>>t;
    while(t--)
    {
        ll ans=0;
        vector<ll> div;
        cin >> n >> m;
        for(ll i=1;i*i<=n;i++)
        {
            if(n%i==0)
            {
                if(i*i==n)
                {
                    if(i>=m) div.push_back(i);
                }
                else
                {
                    if(i>=m) div.push_back(i);
                    if(n/i>=m) div.push_back(n/i);
                }
            }
        }
        for (ll i = 0 ; i <div.size(); i++)
                ans += euler(n/div[i]);
        cout << ans << endl;
    }
}

猜你喜欢

转载自blog.csdn.net/Cassie_zkq/article/details/89503410