zoukankan      html  css  js  c++  java
  • hdu 1796 容斥原理 + longlong

    题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=1796

    How many integers can you find

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


    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
     

     分析:

    1:基本的容斥原理。给定一个N 和一个M集合, 找到小于n 的数中有多少是M中元素的整数倍的  个数。 S= n-1

    设xi 为 S 中能被 M 中 i 个数整除的个数 则 Xans = x1 - x2 + x3 -……+(-1)^(m-1)xm。

    需要注意的是 , 求能被i 个数整除的 个数的时候, 用(n-1)/ lcm(mi)  , 即除以M集合中元素的最小公倍数。

     2: 从组合数学上分析

    设全集 为 S={1 2 3 , ... , n-1}  |s| = n-1;

    M = {m1, m2 , ...  , mm}, 且 M中 个元素互素

    令Qi(i=12, ,,, , m) 表示S中 能被 mi整除的整数这一性质, 令Ai 为S中 具有性质Qi的那些整数所组成的集合。则|A1 υ A2 υ ...υ  Am| 表示S中能被任意mi整除的整数个数。

    |S| -  |A1 υ A2 υ ...υ  Am|  表示 S中 不能被 mi (i = 1, 2 ,...,m) 整除的整数的个数。即S中 与 M 互质的个数。

    又    |A1 υ A2 υ ...υ  Am|  = ∑|Ai| - ∑|Ai ∩ Aj|  + ∑|Ai ∩ Aj ∩ Ak| -...+(-1)^(m-1)|A1 ∩ A2 ∩... ∩Am|

    又    |Ai| = |S| / (mi)     |Ai ∩ Aj|  = |S| / (mi * mj)   同理

    注意:如果M中各个元素不是 互素的 ,则 |Ai| = |S| / (mi)  ,   |Ai ∩ Aj|  = |S| / lcm(mi , mj)    ,正是本题题意。

    3:容斥原理 ,是采用 dfs 搜索, 分别对 M 中的 每个元素mi 枚举,  然后遍历mi ,搜索树,设树根深度为1,  当树深度为偶数,sum-= , 当 树深度为 奇数时 ,sum+=。

    递归图如下:

    本题代码如下:

    #include<iostream>
    #include<stdlib.h>
    #include<stdio.h>
    #include<math.h>
    #include<string.h>
    #include<string>
    #include<queue>
    #include<algorithm>
    #include<map>
    
    using namespace std;
    typedef long long LL;   // 大数 _int64 ,大数输出 // %I64d 
    int n, M;
    int a[22];    // 存储的是M中的值
    LL gcd(LL x, LL  y)   //最大公约数
    {
        return y==0?x:gcd(y,x%y);
    }
    LL lcm(LL x, LL y )    //  最小公倍数
    {
        return x*y/gcd(x,y);
    }
    //         当前点,  搜索树的深度, 记录容斥过程值
    void dfs(int now, int count , LL lcm_1 , LL &sum)
    {
        lcm_1 = lcm(a[now], lcm_1);
        if(count&1)
            sum+=(n-1) / lcm_1;
         else sum-=(n-1) / lcm_1;
         for(int i=now+1 ; i<M ;i++)
            dfs(i,count+1 , lcm_1, sum);    // 搜索方向
    }
    int main()
    {
        int b, len;
        LL sum;
        while(scanf("%d%d",&n,&M)!= EOF)
        {
            sum=0;
            len=0;
            for(int i=0; i<M ; i++)
            {
                scanf("%d",&b);
                if(b)
                    a[len++]= b;
            }
            M=len;
            for( int i=0;i<M;i++)    // 枚举M中集合mi
                dfs(i , 1 ,a[i], sum);
            printf("%I64d
    ", sum);
    
        }
        return 0;
    }
  • 相关阅读:
    node 中的 异步地狱回调
    node 同步和异步的概念
    【Node】File System
    阅读《软技能:代码之外的生存指南》读书笔记
    整理前端学习资料以便日后查看
    【css】单选框和复选框文字垂直居中问题
    [CSS]图片与文字对齐问题--摘自张鑫旭博客
    百度首页换一换功能js实现
    个人加分项
    开课第十五周周总结
  • 原文地址:https://www.cnblogs.com/zn505119020/p/3596279.html
Copyright © 2011-2022 走看看