容斥原理
容斥原理:
假如又4个集合,分别为A, B, C,求这三个集合的并集:
S(a) :表示A集合中元素的个数
S = S(a) + S(b) + S(c)(项的个数是奇数)
- S(a 交 b)- S(a 交 c) - S(b 交 c)(偶数)
+ S(a 交 b 交 c)(奇数)
故可知奇数加偶数减
N个集合的并集的项个数 = 2^N-1 , 所以可以用N个二进制位表示每个项 , 也就是从0 到 1 << N - 1 进行遍历
看题:
给定一个整数nn和mm个不同的质数p1,p2,…,pmp1,p2,…,pm。
请你求出11~nn中能被p1,p2,…,pmp1,p2,…,pm中的至少一个数整除的整数有多少个。
输入格式
第一行包含整数nn和mm。
第二行包含mm个质数。
输出格式
输出一个整数,表示满足条件的整数的个数。
数据范围
1≤m≤161≤m≤16,
1≤n,pi≤1091≤n,pi≤109
输入样例:
10 2
2 3
输出样例:
7
1 #include <iostream> 2 using namespace std; 3 4 typedef long long ll; 5 6 ll p[20]; 7 8 int main(){ 9 int n, m;cin >> n >> m; 10 for(int i = 0;i < m;++i) cin >> p[i]; 11 ll ans = 0; 12 //枚举所有的集合选取情况 2^m - 1种 13 for(int i = 1;i < 1 << m;++i){ 14 ll mul = 1;//用来存当前项所有质数的乘积 15 ll cnt = 0;//质数个数 16 for(int j = 0;j < m;++j) 17 if(i >> j & 1){ 18 if(mul * p[j] > n){ 19 mul = -1; 20 break; 21 } 22 mul *= p[j]; 23 ++cnt; 24 } 25 if(mul != -1){ 26 //奇数加偶数减,ans统计当前这个组合从1到n有多少个数整除p 27 if(cnt % 2) ans += n / mul;//n除一个质数就等于从1到n有多少个数是这个质数的倍数 28 else ans -= n / mul; 29 } 30 } 31 cout << ans << endl; 32 return 0; 33 }
本文来自博客园,作者:SXQ-BLOG,转载请注明原文链接:https://www.cnblogs.com/sxq-blog/p/12285144.html