hdu 1796 How many integers can you find (容斥原理)
hdu1796 题意:给出n(<=2^31)以及m(<=10)个元素组成的无重复元素集合,集合元素0<=a[i]<=20,问有多少个小于n的数能至少被集合中的一个元素整除。
思路:容斥,找到能被一个元素的,被两个元素的…加加减减。 一个元素的最小公倍数定义成自己,然后多个元素的就两个两个算…
一个坑点是,a[i]有0,而一个数除以0没有意义。。。所以读入的时候处理下。。。把0删掉(个人觉得这个坑点毫无技术含量。。。。0不能作为除数这种事情呵呵呵) 并且如果只有一个数且为0,那么删掉后集合就为空了,特判输出0.
另一个坑点是,别看每个数都很小。。但是求多个数的最小公倍数的时候会爆int…
**虽然最后结果没有爆,但是中间量会爆掉,要开long long **
1/* ***********************************************
2Author :111qqz
3Created Time :2016年02月29日 星期一 19时09分31秒
4File Name :code/hdu/1796.cpp
5************************************************ */
6
7#include <cstdio>
8#include <cstring>
9#include <iostream>
10#include <algorithm>
11#include <vector>
12#include <queue>
13#include <set>
14#include <map>
15#include <string>
16#include <cmath>
17#include <cstdlib>
18#include <ctime>
19#define fst first
20#define sec second
21#define lson l,m,rt<<1
22#define rson m+1,r,rt<<1|1
23#define ms(a,x) memset(a,x,sizeof(a))
24typedef long long LL;
25#define pi pair < int ,int >
26#define MP make_pair
27
28using namespace std;
29const double eps = 1E-8;
30const int dx4[4]={1,0,0,-1};
31const int dy4[4]={0,-1,1,0};
32const int inf = 0x3f3f3f3f;
33int n,m;
34int a[15];
35int b[15];
36
37LL gcd ( LL a,LL b)
38{
39 if (b>a) return gcd(b,a);
40 if (a%b==0) return b;
41 return gcd(b,a%b);
42}
43
44LL lcm( LL a,LL b)
45{
46 LL res;
47 res = a*b; //10个数的最小公倍数会爆掉...虽然最终结果不会,但是乘的这一步会,所以要long long
48 res = res/gcd(a,b);
49 return res;
50}
51int main()
52{
53 #ifndef ONLINE_JUDGE
54 freopen("code/in.txt","r",stdin);
55 #endif
56
57 while (~scanf("%d %d",&m,&n)) //m,n和题目中的意思相反,实在看着别扭
58 {
59 int cnt = 0 ;
60 bool zero = false;
61 for ( int i = 0 ; i < n ; i++)
62 {
63 scanf("%d",&b[i]);
64 if (b[i])
65 {
66 a[cnt++] = b[i];
67 }
68 else
69 {
70 zero = true;
71 }
72 }
73
74 if (cnt==0) //只有一个元素且是0...0不能做除数啊。。。这题好蠢
75 {
76 puts("0");
77 continue;
78 }
79
80
81
82 n = cnt;
83
84 LL ans = 0LL ;
85 for ( int msk = 1 ; msk < (1<<n) ; msk++)
86 {
87 int bits = 0 ;
88 LL LCM;
89 for ( int i = 0 ; i < n ; i++)
90 {
91
92 if (msk&(1<<i))
93 {
94 bits++;
95 if (bits==1)
96 {
97 LCM = a[i];
98 }
99 else
100 {
101 LCM = lcm(LCM,LL(a[i]));
102 }
103 }
104 }
105
106 //cout<<"LCM:"<<LCM<<endl;
107 if (bits%2==1)
108 {
109 ans +=LL((m-1)/LCM);
110 }
111 else
112 {
113 ans -=LL((m-1)/LCM);
114 }
115
116 }
117 printf("%lld\n",ans);
118 }
119
120 #ifndef ONLINE_JUDGE
121 fclose(stdin);
122 #endif
123 return 0;
124}
20160305update:也写个递归版本的,好简洁有木有。
1/* ***********************************************
2Author :111qqz
3Created Time :2016年03月05日 星期六 15时23分46秒
4File Name :code/hdu/r1796.cpp
5************************************************ */
6
7#include <cstdio>
8#include <cstring>
9#include <iostream>
10#include <algorithm>
11#include <vector>
12#include <queue>
13#include <set>
14#include <map>
15#include <string>
16#include <cmath>
17#include <cstdlib>
18#include <ctime>
19#define fst first
20#define sec second
21#define lson l,m,rt<<1
22#define rson m+1,r,rt<<1|1
23#define ms(a,x) memset(a,x,sizeof(a))
24typedef long long LL;
25#define pi pair < int ,int >
26#define MP make_pair
27
28using namespace std;
29const double eps = 1E-8;
30const int dx4[4]={1,0,0,-1};
31const int dy4[4]={0,-1,1,0};
32const int inf = 0x3f3f3f3f;
33int n;
34LL m ;
35int a[15];
36int b[15];
37LL LCM;
38LL ans;
39
40LL gcd ( LL a,LL b)
41{
42 if (b>a) return gcd(b,a);
43 if (a%b==0) return b;
44 return gcd(b,a%b);
45}
46
47LL lcm( LL a,LL b)
48{
49 LL res;
50 res = a*b; //10个数的最小公倍数会爆掉...虽然最终结果不会,但是乘的这一步会,所以要long long
51 res = res/gcd(a,b);
52 return res;
53}
54
55void dfs( int id ,LL x,int flag)
56{
57 ans +=flag*(m-1)/x;
58 for ( int i = id+1 ; i < n ; i++)
59 dfs(i,lcm(x,1LL*a[i]),-1*flag);
60
61}
62int main()
63{
64 #ifndef ONLINE_JUDGE
65 freopen("code/in.txt","r",stdin);
66 #endif
67
68 while (~scanf("%lld %d",&m,&n)) //m,n和题目中的意思相反,实在看着别扭
69 {
70 int cnt = 0 ;
71 bool zero = false;
72 for ( int i = 0 ; i < n ; i++)
73 {
74 scanf("%d",&b[i]);
75 if (b[i])
76 {
77 a[cnt++] = b[i];
78 }
79 else
80 {
81 zero = true;
82 }
83 }
84 if (cnt==0) //只有一个元素且是0...0不能做除数啊。。。这题好蠢
85 {
86 puts("0");
87 continue;
88 }
89
90 ans = 0LL;
91 n = cnt;
92 LCM = 0;
93 for ( int i = 0 ; i < n ; i ++)
94 {
95 dfs(i,a[i],1);
96 }
97 printf("%lld\n",ans);
98 }
99
100 #ifndef ONLINE_JUDGE
101 fclose(stdin);
102 #endif
103 return 0;
104}