hdu 4135 Co-prime 【容斥定理应用】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4135

容斥定理求一个区间内与n互素的数有几个;

和模板差不多,只是区间 [1,R] 变成 [L,R],所以可以求出 [1,L] 和 [1,R] 的互素的数的shu'lian再相减,注意这道题的范围;

关于容斥定理的详解  我推荐这篇博客:https://blog.csdn.net/m0_37286282/article/details/78869512#t6

先给出模板:

int solve (int n, int r)
{
    vector<int> p;
    for (int i=2; i*i<=n; ++i)
        if (n % i == 0)
        {
            p.push_back (i);
            while (n % i == 0)
                n /= i;
        }
    if (n > 1)
        p.push_back (n);
    int sum = 0;
    for (int msk=1; msk<(1<<p.size()); ++msk)
    {
        int mult = 1,
            bits = 0;
        for (int i=0; i<(int)p.size(); ++i)
            if (msk & (1<<i))
            {
                ++bits;
                mult *= p[i];
            }
        int cur = r / mult;
        if (bits % 2 == 1)
            sum += cur;
        else
            sum -= cur;
    }
    return r - sum;
}

这是AC代码:

#include<stdio.h>
#include<string.h>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<set>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=1e5+10;

vector<ll>p;

ll solve(ll l,ll r,ll n)
{
    p.clear();
    for(ll i=2;i*i<=n;i++)
    {
        if(n%i==0)
        {
            p.push_back(i);
            while(n%i==0)
                n/=i;
        }
    }
    if(n>1)
        p.push_back(n);
    ll suma=0,sumb=0;
    for(int i=1;i<(1<<p.size());++i)
    {
        ll k=0;
        ll pa=1,pb=1;
        for(int j=0;j<p.size();++j)
        {
            if(i&(1<<j))
            {
                k++;
                pa*=p[j];
                pb*=p[j];
            }
        }
        pa=l/pa;
        pb=r/pb;
        if(k%2==1)
            suma+=pa,sumb+=pb;
        else
            suma-=pa,sumb-=pb;
    }
    return sumb-suma;
}

int main()
{
    int T,cal=0;
    scanf("%d",&T);
    while(T--)
    {
        ll l,r,n;
        scanf("%lld %lld %lld",&l,&r,&n);
        l--;
        printf("Case #%d: %lld\n",++cal,r-l-solve(l,r,n));
    }
    return 0;
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值