题解:
上述题意其实就是求1~n中有多少个是所给四个数字的倍数。
即 ans = n/a + n/b + n/c + n/d - n/lcm(a,b) - n/lcm(a,c) - n/lcm(a,d) - n/lcm(b, c) - n/lcm(b,d) - n/lcm(c,d) + n/lcm(a,lcm(b,c)) + n/lcm(a,lcm(b,d)) + n/lcm(a,lcm(c,d)) + n/lcm(b,lcm(c,d)) - n/lcm(lcm(a,b),lcm(c,d))
Code:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll lcm(ll a,ll b){return a/__gcd(a,b)*b;}
int main()
{
ll n,a[4],ans=0;
cin>>n>>a[0]>>a[1]>>a[2]>>a[3];
for(int i=1;i<(1<<4);i++){
ll x=1;
for(int j=0;j<4;j++){
if(i&(1<<j)){
x=lcm(x,a[j]);
}
}
if(__builtin_popcount(i)&1)ans+=n/x;
else ans-=n/x;
}
cout<<ans<<endl;
return 0;
}
关于容斥原理:
在计数时,必须注意没有重复,没有遗漏。为了使重叠部分不被重复计算,人们研究出一种新的计数方法,这种方法的基本思想是:先不考虑重叠的情况,把包含于某内容中的所有对象的数目先计算出来,然后再把计数时重复计算的数目排斥出去,使得计算的结果既无遗漏又无重复。——摘自百度百科
假设被计数的事物有A、B、C三类,则A类和B类和C类元素个数总和A∪B∪C = A+B+C - A∩B - B∩C - C∩A + A∩B∩C。
根据上式可以发现总共有C(3,1)+C(3,2)+C(3,3)=7种集合情况,为23-1个,又对于A、B、C三类有取和不取,所以我们就可以利用二进制去枚举了。