您的位置:首页 > 其它

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

2017-07-09 09:40 155 查看
先来看一下题目。

题目描述

八是个很有趣的数字啊。八=发,八八=爸爸,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∩(b−a+1−Aa[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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: