题意:
给出n,和m个数,求小于n,且可以被m个数中任意一个整除的数有哪些?
解题思路:
因为 m 很小,用二进制来枚举每种取法。 对于每种取法,求取出来的这些数的LCM,由容斥原理知道,选取的数的个数为奇数时加,偶数时减。 坑点在这 m 个非负数 中有0 。
AC代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
using namespace std ;
#define rep(i,l,p) for(int i=l;i<=p;i++)
#define fread() freopen("in.txt","r",stdin)
#define sf scanf
#define pf printf
typedef long long ll;
long long n,m;
vector <ll> a(20 );
inline long long gcd(long long a,long long b){
return b ? gcd(b,a%b) : a;
}
inline long long lcm(long long a,long long b){
long long res = a*b/abs (gcd(a,b));
return res;
}
int main()
{
while (~sf("%lld%lld" ,&n,&m)){
a.clear();
long long x;
rep(i,1 ,m){
sf("%lld" ,&x);
if (x!=0 ) a.push_back(x);
}
m = a.size();
long long t = 1 <<m;
long long cnt;
ll ans =0 ,res;
for (long long s=0 ;s<t;s++){
cnt = 0 ;
res = 1 ;
rep(i,0 ,m-1 ){
if ((1 <<i) & s) {
res = lcm(res,a[i]);
cnt++;
}
}
if (cnt == 0 ) continue ;
if (cnt&1 ){
ans += (n-1 )/res;
}else {
ans -= (n-1 )/res;
}
}
pf("%lld\n" ,ans);
}
return 0 ;
}