组合数学三
时间限制: 1 Sec 内存限制: 64 MB题目描述
八是个很有趣的数字啊。八=发,八八=爸爸,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。
用Ax来表示在[ a , b ]能被x整除的数,则问题变为求 A8 ∩ (b - a + 1 - A(a[1]) ∪ A(a[2]) ∪ A(a[3]) ∪ .... ∪ A(a[n]) )
Ans = [a , b]中所有能被8整除的数的个数 - [a , b]中既能被8整除又能被其他数整除的数的个数
容斥原理求[a , b]中既能被8整除又能被其他数整除的数的个数
#include<iostream>//容斥原理
#include<cstdio>
#include<cmath>
using namespace std;
typedef unsigned long long ULL;
int a[16],b[16];
int N;
ULL A,B,ans;
ULL gcd(ULL a,ULL b){return b?gcd(b,a%b):a;}
void Dfs(int i,ULL num,int cnt){
if(i>N){
if(cnt&1)
ans+=B/num-A/num;
else ans-=B/num-A/num;
return ;
}
Dfs(i+1,num/gcd(num,a[i])*a[i],cnt+1);
Dfs(i+1,num,cnt);
}
int main(){
scanf("%d",&N);
for(int i=1; i<=N; ++i)
scanf("%d",&a[i]);
scanf("%llu%llu",&A,&B);
Dfs(1,8,1);
printf("%llu\n",ans);
return 0;
}