How many integers can you find
Time Limit: 12000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6362 Accepted Submission(s): 1829
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
题目大意:
给出一个大整数 n, 给出 m 个大整数 a1,a2,a3...a m;
求出 1 - n-1 中, m 个数的倍数有多少
思路:
容斥原理的应用,这个题和当时有个校赛的题目很相似。题目叫 我是好人 其实是个大骗子、当时还不会容斥,没写出来。
后来老师上课讲了用 dfs 实现容斥原理,感觉很厉害!!
1 - n-1 中 a 的倍数有 n-1 / a 个,1 -n-1 中 b 的倍数有 n-1/b个,但是如果简单相加的话,就会把 a 和 b 的倍数重复相加一遍,所以要用到容斥原理进行避免这一个问题。
简单来说就是 n-1/a + n-1 / b - n-1/lcm(a,b)
感想:
啦啦~~觉得自己越来越厉害啦~嘻嘻。
给贴出一个容斥原理讲的特别好的 地址
传送门就绪~
AC代码:
#include<iostream>
#include<stdio.h>
using namespace std;
long long int a[15];
long long int sum,n,pp;
long long int gcd(long long int a,long long int b)
{
if(b==0)
return a;
return gcd(b,a%b);
}
void dfs(int pre,long long int lcm,int nowdep)
{
int i;
lcm=a[pre]*lcm/gcd(a[pre],lcm);
if(nowdep&1)
sum+=(n-1)/lcm;
else
sum-=(n-1)/lcm;
for(i=pre+1;i<pp;i++)
dfs(i,lcm,nowdep+1);
}
int main()
{
int i,m,t;
long long int temp;
while(~scanf("%I64d%d",&n,&m))
{
pp=sum=0;
for(i=0;i<m;i++)
{
scanf("%I64d",&temp);
if(temp!=0)
{
a[pp]=temp;
pp++;
}
}
for(i=0;i<pp;i++)
dfs(i,a[i],1);
cout<<sum<<endl;
}
}