容斥的一个题,site巨巨讲的课的第一个题。入手后还是比较不错的题的,这个dfs如果不好理解一定要模拟一下
解题思路:容斥原理地简单应用。先找出1...n内能被集合中任意一个元素整除的个数,再减去能被集合中任意两个整除的个数,即能被它们两只的最小公倍数整除的个数,因为这部分被计算了两次,然后又加上三个时候的个数,然后又减去四个时候的倍数...所以深搜,最后判断下集合元素的个数为奇还是偶,奇加偶减
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
typedef long long LL;
int n,m,a[30];
LL ans;
int cnt;
LL gcd(LL a,LL b)
{
return b==0?a:gcd(b,a%b);
}
LL dfs(int x,LL b,int id)
{
b=a[x]/gcd(a[x],b)*b;
if(id&1)
ans+=(n-1)/b;
else
ans-=(n-1)/b;
for(int i=x+1;i<cnt;i++)
{
dfs(i,b,id+1);
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
int x;
cnt=0;
for(int i=1;i<=m;i++)
{
scanf("%d",&x);
if(x!=0)
{
a[cnt++]=x;
}
}
ans=0;
for(int i=0;i<cnt;i++)
{
dfs(i,a[i],1);
}
printf("%d\n",ans);
}
return 0;
}