zoukankan      html  css  js  c++  java
  • HDU 1796 Howmany integers can you find (容斥原理)

    How many integers can you find

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


    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
    题意:在m个数的集合中,问在小于n的范围内有多少个数能整除m个数的集合中的数。
    收获: 容斥原理两种表示方法: 1.二进制, 2.递归
    1.二进制
    #include <cstdio>
    #include <iostream>
    #include <cstdlib>
    #include <algorithm>
    #include <ctime>
    #include <cmath>
    #include <string>
    #include <cstring>
    #include <stack>
    #include <queue>
    #include <list>
    #include <vector>
    #include <map>
    #include <set>
    using namespace std;
    
    const int INF=0x3f3f3f3f;
    const double eps=1e-10;
    const double PI=acos(-1.0);
    #define maxn 500
    __int64 k[maxn];
    __int64   gcd(__int64   b,__int64   a)
    {
        return a==0?b:gcd(a,b%a);
    }
    int main()
    {
        int  n, m;
        while(~scanf("%d%d", &n, &m))
        {
            int t;
            n--;
            int cnt = 0;
            for(int i = 0; i < m; i++)
            {
                scanf("%d", &t);
                if(t>0 && t < n)
                    k[cnt++] = t;
            }
            __int64 ans = 0;
            for(int i = 1; i < 1<<cnt; i++)
            {
                int num = 0;
                __int64 lcm = 1;
                for(int j = 0; j < cnt; j++)
                {
                    if(i & (1 << j))
                    {
                        num++;
                        lcm = k[j]/gcd(k[j], lcm) * lcm;
                    }
                }
                if(num & 1)
                    ans += n/lcm;
                else
                    ans -= n/lcm;
            }
            printf("%I64d
    ", ans);
        }
        return 0;
    }

    2. 递归

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    
    using namespace std;
    __int64   a[30];
    int n,m;
    //cur表示
    __int64   sum=0;
    __int64   gcd(__int64   b,__int64   a)
    {
        return a==0?b:gcd(a,b%a);
        //while()
    }//最小公倍数
    void dfs(int cur,__int64   lcm,int id)//容斥原理公式
    {
        //lcm=lcm/gcd(lcm,a[cur])*a[cur];
        lcm=a[cur]/gcd(a[cur],lcm)*lcm;
        if(id&1)//运用了快速幂的方法判断奇偶
            sum+=(n-1)/lcm;
        else
            sum-=(n-1)/lcm;
           // cout<<"id = "<<id<<" : "<<sum<<endl;
        for(int i=cur+1;i<=m;i++)
            dfs(i,lcm,id+1);
    }
    int main()
    {
        int t;
        while(~scanf("%d%d",&n,&t))
        {
            int i,x;
            m=0;
            for(i=1;i<=t;i++)
            {
                scanf("%d",&x);
                if(x)
                 {
                    a[++m]=x;
                 }
            }
            sum=0;
            for(i=1;i<=m;i++)
                dfs(i,a[i],1);
            printf("%I64d
    ",sum);//容斥原理公式
           // cout<<sum<<endl;
        }
        return 0;
    }
  • 相关阅读:
    加密配置节
    配置使用 SQL Server提供程序 。
    文件上传
    未能正确加载包"visla Studio HTM Editor Package" 问题的解决
    AspNetPager分页控件的使用
    配置MIME一览
    摸器械的结果。。。
    爱一个人
    这两天怪哉。。。
    “落花有意随流水,流水无情恋落花。”出处
  • 原文地址:https://www.cnblogs.com/ZP-Better/p/4639606.html
Copyright © 2011-2022 走看看