P1629八
描述
八是个很有趣的数字啊。八=发,八八=爸爸,88=拜拜。当然最有趣的还是8用二进制表示是1000。怎么样,有趣吧。当然题目和这些都没有关系。
某个人很无聊,他想找出[a,b]中能被8整除却不能被其他一些数整除的数。
格式
输入格式
第一行一个数n,代表不能被整除的数的个数。
第二行n个数,中间用空格隔开。
第三行两个数a,b,中间一个空格。
输出格式
一个整数,为[a,b]间能被8整除却不能被那n个数整除的数的个数。
限制
各个测试点1s
提示
对于30%的数据, 1≤n≤5,1≤a≤b≤100000。
对于100%的数据,1≤n≤15,1≤a≤b≤10^9,N个数全都小于等于10000大于等于1。
思路:容斥原理;
先将区间内是8的倍数的求出,然后在用容斥求不能被给的数整除的并且是8的倍数的数。
所以先将没个数与8求下最小公倍数,所以转换成求既能被8除又能被给的数除的数的个数,然后能被8除的总数减去就行。
复杂度(2n);
1 #include<stdio.h> 2 #include<algorithm> 3 #include<iostream> 4 #include<stdlib.h> 5 #include<string.h> 6 #include<math.h> 7 #include<queue> 8 using namespace std; 9 typedef long long LL; 10 LL ans[100]; 11 LL gcd(LL n,LL m); 12 int main(void) 13 { 14 int i,j,k; 15 LL n,m; 16 scanf("%d",&k); 17 for(i=0; i<k; i++) 18 { 19 scanf("%lld",&ans[i]); 20 } 21 scanf("%lld %lld",&n,&m); 22 for(i=0; i<k; i++) 23 { 24 ans[i]=ans[i]/gcd(ans[i],(LL)8)*8; 25 } 26 int cnt=m/8-(n-1)/8; 27 int sum=0; 28 29 for(i=1; i<=(1<<k)-1; i++) 30 { 31 int ak=0; 32 int flag=0; LL cn=1; 33 for(j=0; j<k; j++) 34 { 35 if(i&(1<<j)) 36 { 37 ak++; 38 cn=cn/gcd(cn,ans[j])*ans[j]; 39 if(cn>m) 40 { 41 flag=1; 42 break; 43 } 44 } 45 } 46 if(!flag) 47 { 48 if(ak%2) 49 sum+=m/cn-((n-1)/cn); 50 else sum-=m/cn-((n-1)/cn); 51 } 52 } 53 printf("%d ",cnt-sum); 54 } 55 LL gcd(LL n,LL m) 56 { 57 if(m==0) 58 return n; 59 else if(n%m==0) 60 return m; 61 else return gcd(m,n%m); 62 }