HDU-1796 How many integers can you find(组合数学、dfs)

How many integers can you find

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


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和M个数,问在1~N-1个数中能找出多少个数的因子中有这M个数中的任意一个。
 
集体思路:容斥定理,奇加偶减。从m中第一个数开始遍历,总数减去包含它的两个集合的数、加上包含它的三个集合的数、。。。
 
#include <cstdio>

using namespace std;
const int maxn=15;
int num,m;
long long n,ans,a[maxn];

long long gcd(long long a,long long b)
{
    return b==0?a:gcd(b,a%b);
}

void dfs(int i, long long lcm , int id)
{
    lcm = a[i]/(gcd(a[i],lcm))*lcm;
    if(id%2)
        ans += (n-1)/lcm;
    else
        ans -= (n-1)/lcm;
    for(int j=i+1;j<=num;j++)
        dfs(j,lcm,id+1);
}

int main()
{
    while(scanf("%lld %d",&n,&m)!=EOF)
    {
        int t;
        num=0;
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&t);
            if(t)
                a[++num] = t;
        }
        ans=0;
        for(int i=1;i<=num;i++)
        {
            dfs(i,a[i],1);
        }
        printf("%lld
",ans);
    }
}
原文地址:https://www.cnblogs.com/WWkkk/p/7399330.html