890. 能被整除的数
给定一个整数 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
* 用二进制来表示每个集合的状态:
* 因为至少要选择一个质因数,所以可以选择的质因数方案是:
* C(m,1) + C(m,2) + C(m,3) +...+ C(m,m)
* = 2^m-1;
* 刚好 2^m-1 种集合状态,每个集合选择的质因数数量又恰好对应1~2^m-1 用二进制表示
* 的1的数量,且每个位置i上的 1 表示该集合选择了第i个质因数 (p[i]);
* 比如,在1~ 2^m-1 中,只用一位1的数,有C(m,1)种选择;只有两位1的数,有C(m,2)种选择,
* 且每种选择都不会存在用二进制表示的数上1的组合位置是完全一样的,(有两组数用
* 二进制表示的1的个数都是2,且第一组上1的位置是 i,j,第二组上1的位置是 k,l,那么
* 必定有不存在 i==k && j==l(不可能两两相等),其他情况也是必定存在这样的结论)。
* 所以用 1~2^m-1 刚好等对应不同集合的选择情况。
/**
* 用二进制来表示每个集合的状态:
* 因为至少要选择一个质因数,所以可以选择的质因数方案是:
* C(m,1) + C(m,2) + C(m,3) +...+ C(m,m)
* = 2^m-1;
* 刚好 2^m-1 种集合状态,每个集合选择的质因数数量又恰好对应1~2^m-1 用二进制表示
* 的1的数量,且每个位置i上的 1 表示该集合选择了第i个质因数 (p[i]);
* 比如,在1~ 2^m-1 中,只用一位1的数,有C(m,1)种选择;只有两位1的数,有C(m,2)种选择,
* 且每种选择都不会存在用二进制表示的数上1的组合位置是完全一样的,(有两组数用
* 二进制表示的1的个数都是2,且第一组上1的位置是 i,j,第二组上1的位置是 k,l,那么
* 必定有不存在 i==k && j==l(不可能两两相等),其他情况也是必定存在这样的结论)。
* 所以用 1~2^m-1 刚好等对应不同集合的选择情况。
*/
#include <iostream>
using namespace std;
typedef long long LL;
const int maxn = 20;
int p[maxn];
int main()
{
int n,m;
cin >> n >> m;
for(int i=0;i<m;++i)
cin >> p[i];
LL res=0;
for(int i=1;i< 1<<m ;++i)
{
LL t=1;
int cnt=0;
for(int j=0;j<m;++j)
{
if(i>>j & 1)
{
t*=p[j]; //累乘分母
++cnt;
if(t>n) //当分母大于n
{
t=-1;
break;
}
}
}
if(t!=-1)
{
if(cnt%2) //奇数个相加
res+=n/t;
else //偶数个相减
res-=n/t;
}
}
cout << res << endl;
return 0;
}