How many integers can you find
Time Limit: 12000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3132 Accepted Submission(s): 884
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进行不断找约数从而实现寻找到ans的过程。
先上代码长但是时间上较为优化的版本,即利用dfs对二进制串进行遍历:
#include <cstdio>
using namespace std;
typedef long long ll;
int n,m,a[11];
ll ans;
ll gcd(ll a,ll b)
{
return b==0?a:gcd(b,a%b);
}
ll lcm(ll a,ll b)
{
return a/gcd(a,b)*b;
}
void dfs(int deep,int num,ll _lcm)
{
if(deep>m)
{
if(num==0)
return;
if(num&1)
ans+=(ll)n/_lcm;
else
ans-=(ll)n/_lcm;
return;
}
dfs(deep+1,num,_lcm);
dfs(deep+1,num+1,lcm(_lcm,(ll)a[deep]));
}
int main()
{
while(scanf("%d%d",&n,&m)==2)
{
--n,ans=0;//有坑,一定要记得是小于n的数去产生ans。
int i,j=1;
for(i=1;i<=m;++i)
{
scanf("%d",&a[j]);//有坑,一定要记得把是0时候的a[i]剔除
if(a[j]) ++j;
}
m=j-1;
dfs(1,0,1);
printf("%I64d\n",ans);
}
return 0;
}
再上代码短,但是较为缓慢的版本,即对二进制直接通过for循环进行遍历:
8980017 | 2013-08-18 10:35:56 | Accepted | 1796 | 984MS | 232K | 781 B | C++ | love_FDU_llp |
#include <cstdio>
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b)
{
return b==0?a:gcd(b,a%b);
}
ll lcm(ll a,ll b)
{
return a/gcd(a,b)*b;
}
int main()
{
int n,m,a[11];
ll ans;
while(scanf("%d%d",&n,&m)==2)
{
int i,j=0;
ans=0;
for(i=0;i<m;++i)
{
scanf("%d",&a[j]);
if(a[j]) ++j;
}
m=j,--n;
for(i=1;i<(1<<m);++i)
{
int num=0;
ll _lcm=1;
for(j=0;j<m;++j)
if(i&1<<j) ++num,_lcm=lcm(_lcm,a[j]);
if(num&1)
ans+=(ll)n/_lcm;
else
ans-=(ll)n/_lcm;
}
printf("%I64d\n",ans);
}
return 0;
}
二者时间上相差了将近4倍,这是为什么呢?
尽管dfs时有一个开栈再归栈这一浪费时间的过程,但是通过dfs,我们可以不对二进制串中的0,1枚举,
从而实现了常优!