Time Limit: 12000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 7520 Accepted Submission(s): 2228
Problem Description
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
Source
题意:有一个数n,和一个拥有m个元素的集合,求在小于n的正整数中能被集合m中任意元素整除的整数个数。
题解:容斥原理,先求出能被一个元素整除的整数个数,再减去能被两个元素整除的整数个数,再加上能被三个元素整除的整数个数,以此类推。
注意:此题在容斥是,计算的是k个元素最小公倍数,而不是乘积。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
#include<iostream>
#include<cstdio>
using namespace std;
long long s;
long long m;
int n;
int count_=1;
int a[25];
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
int lcm(int a,int b)
{
return a/gcd(a,b)*b;
}
void dfs(int k,long long ans,int cou,int j)
{
if(cou==k)
{
s+=(m-1)/ans;
return ;
}
for(int i=j; i<=n; i++)
{
int aa=ans;
ans=lcm(ans,a[i]);
cou++;
dfs(k,ans,cou,i+1);
cou--;
ans=aa;
}
return ;
}
int main(void)
{
while(~scanf("%lld%d",&m,&n))
{
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
{
if(a[i]==0)
{
for(int j=i;j<=n;j++)
a[j]=a[j+1];
n--;
}
}
long long sum=0;
for(int i=1; i<=n; i++)
sum+=((m-1)/a[i]);
for(int i=2; i<=n; i++)
{
s=0;
dfs(i,1,0,1);
if(i%2==0)sum+=(-1)*s;
else sum+=s;
}
printf("%lld\n",sum);
count_=1;
}
return 0;
}