UVA 10325 lottery 容斥原理
题意: 给定 n,m 和 m 个数 ,求 1~n 中 不能 能被 m个数中的任意 一个数整除 的个数
题解:
首先明白对于集合[1,n]内能被a整除的数的个数为n/a,既能被a整除又能被b整除的数的个数为n/lcm(a,b)(a,b的最小公倍数);
容斥原理地简单应用。先找出1...n - 1内能被集合M中任意一个元素整除的个数,再减去能被集合中任意两个整除的个数,即能被它们俩的最小公倍数整除的个数,因为这部分被计算了两次,然后又加上三个时候的个数,然后又减去四个时候的倍数...直接枚举状态0...(1<<m),然后判断状态内涵几个集合元素,然后计算lcm和能被整除的个数,最后判断下集合元素的个数为奇还是偶,奇加偶减。这里回溯搜索M元素的组合也行
1 #include<cstdio>
2 #include<cstring>
3 #include<cmath>
4 #include<iostream>
5 #include<algorithm>
6 #include<set>
7 #include<map>
8 #include<queue>
9 #include<vector>
10 #include<string>
11 #define inf 0x7fffffff
12 #define maxn 60000
13 #define CL(a,b) memset(a,b,sizeof(a))
14 #define ll long long
15 using namespace std;
16 ll n , m ;
17 ll a[20] ;
18 ll gcd(ll a,ll b)
19 {
20
21 if(b == 0) return a;
22
23 return gcd(b,a%b) ;
24
25 }
26 ll lcm(ll a,ll b)
27 {
28 ll d = gcd(a,b) ;
29
30 return a*b/d ;
31 }
32 int main()
33 {
34 int i ;
35 while(scanf("%lld%lld",&n,&m)!=EOF)
36 {
37 ll ans= 0 ;
38 for(i = 0 ;i < m;i++ )
39 {
40 scanf("%lld",&a[i]) ;
41
42 }
43
44
45 ll sum = 0 ;
46 for(ll msk = 1 ; msk < (1<< m); msk++)// 所有的情况
47 {
48
49
50 ll mul = 1;
51
52 ll bits = 0 ;
53
54 for(int j = 0 ; j < m;j++)
55 {
56
57
58 if(msk & (1 << j))
59 {
60
61 bits ++ ;
62 mul = lcm(mul, a[j]) ;
63 if(mul > n)break ;
64
65
66 }
67
68
69
70
71 }
72
73 if(mul > n) continue ;
74
75 ll cur = n/mul ;
76
77
78 if(bits & 1 )
79 {
80 sum += cur ;
81 }
82 else sum -= cur ;
83
84 }
85
86
87 printf("%lld\n",n - sum ) ;
88
89
90
91 }
92
93 }
2 #include<cstring>
3 #include<cmath>
4 #include<iostream>
5 #include<algorithm>
6 #include<set>
7 #include<map>
8 #include<queue>
9 #include<vector>
10 #include<string>
11 #define inf 0x7fffffff
12 #define maxn 60000
13 #define CL(a,b) memset(a,b,sizeof(a))
14 #define ll long long
15 using namespace std;
16 ll n , m ;
17 ll a[20] ;
18 ll gcd(ll a,ll b)
19 {
20
21 if(b == 0) return a;
22
23 return gcd(b,a%b) ;
24
25 }
26 ll lcm(ll a,ll b)
27 {
28 ll d = gcd(a,b) ;
29
30 return a*b/d ;
31 }
32 int main()
33 {
34 int i ;
35 while(scanf("%lld%lld",&n,&m)!=EOF)
36 {
37 ll ans= 0 ;
38 for(i = 0 ;i < m;i++ )
39 {
40 scanf("%lld",&a[i]) ;
41
42 }
43
44
45 ll sum = 0 ;
46 for(ll msk = 1 ; msk < (1<< m); msk++)// 所有的情况
47 {
48
49
50 ll mul = 1;
51
52 ll bits = 0 ;
53
54 for(int j = 0 ; j < m;j++)
55 {
56
57
58 if(msk & (1 << j))
59 {
60
61 bits ++ ;
62 mul = lcm(mul, a[j]) ;
63 if(mul > n)break ;
64
65
66 }
67
68
69
70
71 }
72
73 if(mul > n) continue ;
74
75 ll cur = n/mul ;
76
77
78 if(bits & 1 )
79 {
80 sum += cur ;
81 }
82 else sum -= cur ;
83
84 }
85
86
87 printf("%lld\n",n - sum ) ;
88
89
90
91 }
92
93 }