HDU 1796How many integers can you find(容斥原理)
Description
Now you get a number N, and a M-integers set, you should find out how many integers which are small than N, that they can divided exactly by any integers in the set. For example, N=12, and M-integer set is {2,3}, so there is another set {2,3,4,6,8,9,10}, all the integers of the set can be divided exactly by 2 or 3. As a result, you just output the number 7.
Input
There are a lot of cases. For each case, the first line contains two integers N and M. The follow line contains the M integers, and all of them are different from each other. 0<N<2^31,0<M<=10, and the M integer are non-negative and won’t exceed 20.
Output
For each case, output the number.
Sample Input
12 2 2 3
Sample Output
7
分析:这几天练容斥有感觉,知道是容斥,但是却有问题,容斥是 互质的数,然后对于2,4这样的数就不会做了,太肤浅了,直接求最小公倍数啊,对啊,互质的相乘就是因为最小公倍数就是乘积啊=_=,弱!
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 using namespace std; 6 typedef long long LL; 7 int num[30], n, m, a[30]; 8 LL res; 9 LL gcd(LL a, LL b) 10 { 11 if (a == 0) 12 return b; 13 return gcd(b % a, a); 14 } 15 void dfs(int cur, int snum, int cnt) 16 { 17 if (snum == cnt) 18 { 19 int temp = n; 20 int mult = 1; 21 for (int i = 0; i < snum; i++) 22 mult = mult / gcd(mult, a[i]) * a[i]; // 防爆 23 if (mult == 0) 24 return; 25 if (temp % mult == 0) 26 res += temp / mult - 1; 27 else 28 res += temp / mult; 29 return; 30 } 31 for (int i = cur; i < m; i++) 32 { 33 a[snum] = num[i]; 34 dfs(i + 1, snum + 1, cnt); 35 } 36 } 37 int main() 38 { 39 int tm; 40 while (scanf("%d%d", &n, &tm) != EOF) 41 { 42 m = 0; 43 for (int i = 0; i < tm; i++) 44 { 45 int temp; 46 scanf("%d", &temp); // 去0 47 if (temp) 48 num[m++] = temp; 49 } 50 LL sum = 0; 51 for (int i = 1; i <= m; i++) 52 { 53 res = 0; 54 dfs(0, 0, i); 55 if (i & 1) 56 sum += res; 57 else 58 sum -= res; 59 } 60 printf("%I64d\n", sum); 61 } 62 return 0; 63 }