这篇文章中讲到这个问题,这篇文章基本上把容斥原理解决的问题大体上都概括了,神文啊。http://www.cppblog.com/vici/archive/2011/09/05/155103.html
题意:给出n,和一些数字,求1-n-1之间多少个数能被这些数整除的。思路,去看上面这篇文章吧,注意预处理把数据这些数中0和整除的数给筛出来,取交集的时候求的是lcm,就没问题了。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <cmath> 5 #define ll __int64 6 using namespace std; 7 int p[20],o[20]; 8 ll gcd(ll a,ll b) 9 { 10 return b == 0 ? a:gcd(b,a%b); 11 } 12 int judge(int a,int len) 13 { 14 int i,j,num; 15 ll lcm,ans; 16 ans = 0; 17 for(i = 1;i < 1<<len;i ++) 18 { 19 num = 0;lcm = 1; 20 for(j = 0;j <= len-1;j ++) 21 { 22 if(i&(1<<j)) 23 { 24 num ++; 25 lcm = lcm*p[j]/gcd(lcm,p[j]); 26 } 27 } 28 if(num&1) 29 ans += a/lcm; 30 else 31 ans -= a/lcm; 32 } 33 return (int)ans; 34 } 35 int main() 36 { 37 int n,m,i,j; 38 while(scanf("%d%d",&n,&m)!=EOF) 39 { 40 memset(o,0,sizeof(o)); 41 for(i = 0; i <= m-1; i ++) 42 scanf("%d",&p[i]); 43 sort(p,p+m); 44 for(i = 0; i <= m-1; i ++)//预处理一下,写的有点繁琐 45 { 46 if(p[i] == 0) 47 { 48 o[i] = 1; 49 continue; 50 } 51 if(!o[i]) 52 { 53 for(j = i+1; j <= m; j ++) 54 { 55 if(p[j]%p[i] == 0) 56 o[j] = 1; 57 } 58 } 59 } 60 j = 0; 61 for(i = 0;i <= m-1;i ++) 62 { 63 if(!o[i]) 64 p[j++] = p[i]; 65 } 66 m = j; 67 printf("%d\n",judge(n-1,m)); 68 } 69 return 0; 70 }