【组合数学】八(容斥原理)

版权声明:本文为博主原创文章,转载请注明本页地址。 https://blog.csdn.net/C20180630/article/details/74857317

先来看一下题目。

题目描述

八是个很有趣的数字啊。八=发,八八=爸爸,88=拜拜。当然最有趣的还是8用二进制表示是1000。怎么样,有趣吧。当然题目和这些都没有关系。 某个人很无聊,他想找出[a,b]中能被8整除却不能被其他一些数整除的数。

输入

第一行一个数n,代表不能被整除的数的个数。 第二行n个数,中间用空格隔开。 第三行两个数a,b,中间一个空格。 a < =b < =1000000000

输出

一个整数,为[a,b]间能被8整除却不能被那n个数整除的数的个数。

样例输入

3
7764 6082 462
2166 53442

样例输出

6378

提示

对于30%的数据, 1 ≤n ≤5,1 ≤a ≤ b ≤ 100000。
对于100%的数据,1 ≤ n ≤15,1 ≤ a ≤ b ≤ 10^9,N个数全都小于等于10000大于等于1。

分析

估计这道题80%的人看完题目过后就知道这道题的解法——容斥原理。我一开始就想到了,只是在考试的过程中没有实现%>_<% ,然后就没有AC.
所以用 Ax 来表示在区间内能被x整除的数,则问题就变为求

A8(ba+1Aa[1]Aa[2]Aa[3]....Aa[n])

Ans=[a,b]中所有能被8整除的数的个数-[a,b]中既能被8整除又能被其他数整除的数的个数
容斥原理求[a,b]中既能被8整除又能被其他数整除的数的个数

源代码

#include<cstdio>
#define LL long long
int n;
LL a,b,num[20],ans;
LL gcd(LL a,LL b){return b==0?a:gcd(b,a%b);}
LL lcm(LL a,LL b){return a*b/gcd(a,b);}
void dfs(int i,LL tmp,int cnt){
    if(i>n){
        if(cnt&1) ans+=b/tmp-a/tmp;
        else ans-=b/tmp-a/tmp;  
    }
    else{
        dfs(i+1,lcm(tmp,num[i]),cnt+1);
        dfs(i+1,tmp,cnt);
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld",&num[i]);
    scanf("%lld%lld",&a,&b);
    dfs(1,8,1);
    printf("%lld",ans);
}

猜你喜欢

转载自blog.csdn.net/C20180630/article/details/74857317