hdu2588gcd-欧拉函数应用

152 篇文章 0 订阅
2 篇文章 0 订阅

题意:

给定T组数据,每组数据N,M

询问有多少个 1<=x<=n  gcd(n,x)>=m

思路:

以前只是知道欧拉函数(当然求还是靠板子)有用来求从1-n-1中 与n互质的个数,这个题是一个应用

欧拉函数是求比 euler(q) 所有比q小的与q互素的数。那么如果得到有ans个与q互素的数字,乘以我们枚举的d就会得到ans个数字,这ans个数字中的每一个都满足我们所需要的:

gcd(x,n)==d

(x,n)>=是题目要求->

设 gcd(x,n)==d    p 与 q 分别是 在等式1.2中d的系数 

x= p * d

 n=q * d;

其中d>=m

当我们枚举确定了d之后,自然可以求出q,  因为我们当前确定gcd(x,n)==d 所以 q与p一定互质。因此对于q的欧拉函数个数即使当前d下 x的可以取值个数。依次枚举

注意:

如果我们从m->n枚举会TLE。

优化:

如果我们确定了一个d,我们可以得知d的满足条件,同时如果d>=m 那么求他的系数n/d的欧拉函数

反之-->如果n/d>=m 那么他的系数d也必定满足条件。求i的欧拉函数即可

具体见代码


#include <iostream>
#include <stdio.h>

using namespace std;
typedef long long ll;
ll n,m;
ll res=0;
void euler(ll x)
{
    ll ans;
    ans=x;
    for(int i=2; i*i<=x; ++i)
    {
        if(x==1)
            break;
        if(x%i==0)
        {
            ans=ans/i*(i-1);
            while(x%i==0)
                x/=i;
        }
    }
    if(x!=1)
    {
        ans=ans/x*(x-1);
    }
    res+=ans;
    return ;
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n>>m;
        res=0;
        for(ll i=1;i*i<=n ;i++  )
        {
            if(n%i)
                continue;

            if(i>=m)
            euler(n/i);
            if((n/i)!=i&&(n/i)>=m)
            euler(i);
            //euler(i);
            // printf("%lld\n",res);
        }
        cout<<res<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值