容斥原理
蒟蒻打不来LaTeX;口头描述一下,大概就是:
设S1,S2,…Sn;为有限集合,|S|表示集合的大小;
所有集合的并集为
奇数个集合的交集减去偶数个集合的交集;
例题
给定一个整数 n 和 m 个不同的质数 p1,p2,…,pm。
请你求出 1∼n 中能被 p1,p2,…,pm 中的至少一个数整除的整数有多少个。
输入格式
第一行包含整数 n 和 m。
第二行包含 m 个质数。
输出格式
输出一个整数,表示满足条件的整数的个数。
数据范围
1≤m≤16,
1≤n,pi≤109
输入样例:
10 2
2 3
输出样例:
7
#include<iostream>
#include<algorithm>
using namespace std;
#define int long long
const int N=20;
int n,m,p[N];
signed main()
{
scanf("%lld%lld",&n,&m);
for(int i=0;i<m;i++)scanf("%lld",&p[i]);//因为接下来要用到位运算和状态压缩所以从0开始
int ass=0;
for(int i=1;i< 1<<m;i++){//枚举所有状态状态压缩;
int t=1,cnt=0;// t表示暂时的积 cnt表示该状态之内的选取的数的个数
for(int j=0;j<m;j++)//枚举每一位
if(i>>j&1){
cnt++;
if(t*p[j] > n){
t=-1;break;
}
t*=p[j];
}
if(t!=-1){
if (cnt%2)ass+=n/t;//是奇数的集合则加上去
else ass-=n/t;//是偶数的集合则减去
}
}
printf("%lld",ass);
return 0;
}