原题传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1796
Sample Input
12 2
2 3
Sample Output
7
题目大意:给你两个整数n和m,m是一个整数集合的个数,我们所需要求的是1->n-1中有多少数可以被该整数集合某个元素整除。
解题思路:需要用到容斥定理。根据集合里的元素,遇奇则加,遇偶则减(其实就是羡慕别人一对对的)。遇奇则加中的奇意思是用到m中奇数个元素,同理,偶也是如此。具体看代码。
然后有一点需要注意,由于集合中的元素可能并不互质,所以可能会多加或多减一部分,所以我们需要用到lcm。其他就是容斥定理的模板了,其实我也刚学,模板可能很快就忘了。(⊙﹏⊙)b,还要排除掉0的干扰。
Code:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
ll n;
ll gcd(ll a,ll b){//最大公约数
return b?gcd(b,a%b):a;
}
int main(){
ll m,a[15],b[15];
while(cin>>n>>m){
int c=0;
memset(a,0,sizeof(a));
for(int i=1;i<=m;i++){
cin>>a[i];
if(a[i]!=0){//排除掉0
b[c++]=a[i];
}
}
ll ans=0;
for(int i=1;i<(1<<m);i++){
ll cnt=0,sum=1;
for(int j=0;j<m;j++){
if(1&(i>>j)){
cnt++;//cnt表示用到元素的个数
sum=sum*b[j]/gcd(sum,b[j]);//两个数相乘除以他们的最大公约数就是他们的最小公倍数
}
}
if(1&cnt){//遇奇则加
ans+=(n-1)/sum;
}
else {//遇偶则减
ans-=(n-1)/sum;
}
}
cout<<ans<<endl;
}
return 0;
}