How many integers can you find
Time Limit: 12000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 9580 Accepted Submission(s): 2876
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
Author
wangye
Source
Recommend
wangye
大致题意就是,给你一个整数N,和一个集合,找出小于N的 被集合里的任意一个整数整除的数有多少个
//第一次接触容斥定理,我看了好久的容斥定理到编码的过程,找了别的题看了看大概明白了,,这道是简单型的 还要看看别的
//容斥定理讲解http://blog.youkuaiyun.com/TRiddle/article/details/51873991
所以大致代码借大神的理解着写
注意0不要忘
#include<cstdio>
#include<cmath>
#include<algorithm>
#define LL long long
using namespace std;
LL num[25];
LL n,m;
LL gcd(LL a,LL b)
{
int r;
while(b!=0)
{
r=b;
b=a%b;
a=r;
}
return a;
}
LL lcm(LL a,LL b)
{
return a/gcd(a,b)*b;
}
LL solve()
{
LL ans = 0;
for (LL i = 1 ; i <(1<<m) ; i++)
{
LL ant = 0;
LL k = 1;
for (LL j = 0 ; j < m; j++)
{
if (i & (1<<j))
{
ant++;
k=lcm(k,num[j]);//因为m集合内的数不一定是质数,所以当集合内数累乘时应求其最小公倍数。
}
}
if (ant & 1)
ans += n / k;//奇加偶减
else
ans -= n / k;
}
return ans;
}
int main()
{
LL i;
while(~scanf("%lld %lld",&n,&m))
{
n=n-1;//不包括n
for(i=0;i<m;i++)
{
scanf("%lld",&num[i]);
if(num[i]==0) //m集合内的数可能有0,将情况排除
{
i--;
m--;
}
}
sort(num,num+m);
printf ("%lld\n",solve());
}
return 0;
}