Now you get a number N, and a M-integers set, you should find out how many integers which are small than N, that they can divided exactly by any integers in the set. For example, N=12, and M-integer set is {2,3}, so there is another set {2,3,4,6,8,9,10}, all the integers of the set can be divided exactly by 2 or 3. As a result, you just output the number 7.
Input
There are a lot of cases. For each case, the first line contains two integers N and M. The follow line contains the M integers, and all of them are different from each other. 0<N<2^31,0<M<=10, and the M integer are non-negative and won’t exceed 20.
Output
For each case, output the number.
Sample Input
12 2
2 3
Sample Output
7
题意:
题目大意:给定n和一个大小为m的集合,集合元素为非负整数。求1…n内能被集合里任意一个数整除的数字得总个数。n<=2^31,m<=10
思路
我知道是容斥定理,但是不知道怎么去想;想了好长时间才想明白;
按题中给的数据 n =12,m = 2,集合为2 , 3;
首先选2: 11/2=5 ,3: 11/3=3;
然后选2,3: 11 /(2*3)=1;
容斥定理 :5+3-1=7;
关于这一题:
我们记num(x1, x2, x3…xn)为能被xi整除的数的个数(x1, x2…xn,为m集合中的数),那么最终的答案就是num(x1) + num(x2) + … + num(xn) - num(x1, x2) - num(x1, x3) - …- num(xn - 1, xn) + num(x1, x2, x3) + … +…等等,
也就是容斥公式:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
typedef long long ll;
ll a[20],b[20];
int main()
{
int n,m;
while(~scanf("%d %d",&n,&m)&&n&&m)
{
int cot=0;
ll ans=0;
for(int i=0;i<m;i++)//集合中可能含有0,所以要把0去除
{
scanf("%lld",&a[i]);
if(a[i]!=0)
b[cot++]=a[i];
}
for(int i=1;i<(1<<cot);i++)//一共cot个数字,所以有2^cot个选择
{
ll sum=1;
ll cnt=0;
for(int j=0;j<cot;j++)//每一种方案都判断第j个物品该不该选择
{
if(1&(i>>j))
{
cnt++;
sum*=b[j]/__gcd(sum,b[j]);//求出来cnt个数的最大公约数sum,如果能被sum整除,那么一定能够被选中的数整除
}
}
if(cnt&1)//如果选择了奇数个数字,那么就用加法
ans+=(n-1)/sum;
else ans-=(n-1)/sum;
}
printf("%lld\n",ans);
}
return 0;
}