现在的位置: 首页 > 综合 > 正文

HDOJ 1796 枚举

2018年01月20日 ⁄ 综合 ⁄ 共 1384字 ⁄ 字号 评论关闭

How many integers can you find

Time Limit: 12000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1219    Accepted Submission(s): 282

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
 

具体做法是去枚举集合,总共会有1<<m种,这里运用到了二进制位运算。

比起容斥原理中的DFS,我更喜欢这种计算方法。

 

#include<stdio.h>

__int64 a[15];

__int64 gcd(__int64 a,__int64 b)
{
    if(b==0)
        return a;
    else
        return gcd(b,a%b);
}

__int64 lcm(__int64 a,__int64 b)
{
    __int64 g=gcd(a,b);
    return a*b/g;
}

int main()
{
    __int64 n,m,i,j,k,s,ans,num;
    while(scanf("%I64d%I64d",&n,&m)!=EOF)
    {
        num=0;
        for(i=0;i<m;i++)
        {
            scanf("%I64d",&a[i]);
            if(a[i]>0)
                a[num++]=a[i];
        }
        ans=0,m=num;
        for(i=1;i<(1<<m);i++)
        {
            s=1;
            k=0;
            for(j=0;j<m;j++)
            {
                if((i>>j)&1)
                {
                    s=lcm(s,a[j]);
                    k++;
                }
            }
            if(k&1)
                ans=ans+(n-1)/s;
            else
                ans=ans-(n-1)/s;
        }
        printf("%I64d\n",ans);
    }
    return 0;
}

抱歉!评论已关闭.