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
解题思路:容斥原理地简单应用。先找出1...n内能被集合中任意一个元素整除的个数,再减去能被集合中任意两个整除的个数,即能被它们两只的最小公倍数整除的个数,因为这部分被计算了两次,然后又加上三个时候的个数,然后又减去四个时候的倍数
有几点需要注意:
①m里的值可能是0
②m的值可能不互质,这时候取数的时候不能直接相乘,要求LCM( )(比如(2,4),能被4整除的都能被2整除,这部分数加了两次,减去2和4的最小公倍数即能被4整除的这部分数)
③m里的数可能大于等于n
④n要减一
AC代码:
#include<iostream>
using namespace std;
int n,m,q[30];
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
int lcm(int a,int b)
{
return a/gcd(a,b)*b;//先除在乘,避免超int
}
int nop()//容斥原理
{
int flag,num,sum=0;
for(int i=1;i<(1<<m);i++)//二进制枚举
{
flag=0;
num=1;
for(int j=0;j<m;j++)
{
if(i >> j & 1)
{
flag++;//计数
num=lcm(num,q[j]);
}
}
if(flag&1)//奇加偶减
sum+=n/num;
else
sum-=n/num;
}
return sum;
}
int main()
{
while(cin>>n>>m)
{
n--;
for(int i=0;i<m;i++)
{
cin>>q[i];
if(q[i]<1||q[i]>=n)//大于n和小于1的删除
{
i--;
m--;
}
}
int ans=nop();
cout<<ans<<endl;
}
return 0 ;
}