hdu4135 Co-prime

题意:

给定a,b,n,要求求出a~b区间内与n互质的数的对数。

思路:

乍一看是到欧拉函数的题目(终于不是欧拉函数假扮最大公约数了),可是仔细一想这里的坑:n的数据范围虽然比a、b要大,可是n确实有可能会小于a、b呀,欧拉原理只能求小于n的与n互质的数字的个数,即这里欧拉函数失效了。

所以正确的思路是,容斥原理。

因为[a,b] = [1,b]-[1,a-1],那么同时算出1~b内与n不互质的数的个数和1~a-1内与n不互质的数的个数,两者相减即可。

容斥原理利用的dfs来做,唉唉,看了一会儿dfs的例题,会了一点点,这里终于没有原来那么痛苦了,但是还是有点迷糊

代码:

#include <stdio.h>
#include <algorithm>
 
using namespace std;
 
typedef long long ll;
const int N = 1005;
 
ll a, b, n, cnt, num[N], ansa, ansb;
//求出所有的质因子,并存储到数组里面
void euler(ll n)
{
    for(int i = 2; i*i <= n; i++)
    {
        if(n%i == 0)
        {
            num[cnt++] = i;
            while(n%i == 0)
                n /= i;
        }
    }
    if(n > 1) num[cnt++] = n;
}
 
 //最大公约数
ll gcd(ll a, ll b)
{
    if(b == 0) return a;
    return gcd(b, a%b);
}
 //最小公倍数
ll lcm(ll a, ll b)
{
    return a*b/gcd(a, b);
}
 //利用dfs实现容斥原理
void dfs(ll th, ll now, ll step)
{
    if(step > cnt) return;
    //n的now因子和第th个因子的最小公倍数
    //他一定是与n不互质的,因为它的因子都是n的
    ll LCM = lcm(now, num[th]);
    //容斥原理的精髓
    //第奇数个要加
    if(step&1)
    {
        ansa += a/LCM;
        ansb += b/LCM;
    }
    //第偶数个要减
    else
    {
        ansa -= a/LCM;
        ansb -= b/LCM;
    }
    //接下来选下面的数,层数++,
    for(ll i = th+1; i < cnt; i++)
        dfs(i, LCM, step+1);
}
 
int main()
{
    int t, Case = 1;
    scanf("%d", &t);
    while(t--)
    {
        cnt = 0;
        ansa = ansb = 0;
        scanf("%lld%lld%lld", &a, &b, &n);
        a-=1;
        euler(n);//求出n的质因子
        //cut为质因子的个数
        for(int i = 0; i < cnt; i++)
        {
            //第i个因子选的是num[i]
            //step是深搜层数,一共最多选cut个,所以最多有cut层,等于的话就return了。
            dfs(i, num[i], 1);
        }
        printf("Case #%d: %lld\n", Case++, (b-a) - (ansb-ansa));
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值