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

    题意:
          求区间(0,n)之间能被集合A内一个元素整除的数的个数,例如n = 12, A = {2, 3}
          则能被A集合元素整除的数的集合为{2,3,4,6,8,9,10}则结果为7。

    http://acm.hdu.edu.cn/showproblem.php?pid=1796

    #include<iostream>
    #include<cstdio>
    using namespace std;
    #define LL long long
    int len,num[20];
    LL n,sum;
    LL gcd(LL a,LL b)
    {
        if(b==0) return a;
        return gcd(b,a%b);
    }
    void dfs(LL lcm,int sta,int cnt)//最小公倍数为lcm时再加入num[sta]后的答案
    {
        lcm=lcm*num[sta]/gcd(lcm,num[sta]);          //求集合前面几个数的最小公倍数
        if(cnt&1)sum+=n/lcm;
        else sum-=n/lcm;          //这里减去重复计算的数,这时整个代码的精华
        for(int i=sta+1;i<len;i++) dfs(lcm,i,cnt+1);
    }
    int main()
    {
        int m;
        while(cin>>n>>m)
        {
            len=0;
            for(int i=0;i<m;i++)
            {
                int x;
                cin>>x;
                if(x==0)continue;
                num[len++]=x;
            }
            n--;
            sum=0;
            for(int i=0;i<len;i++) dfs(num[i],i,1);
            cout<<sum<<endl;
        }
    }


    二进制组合生成法(比上面的慢3倍)

    #include <iostream>
    using namespace std;
    int arr[30];
    int n,m;
    int gcd(int a,int b)
    {
        if(b==0) return a;
        return gcd(b,a%b);
    }
    int solv(int s)
    {
        int cnt=0;
        long long lcm=1;
        for(int i=0;i<m;i++) if(s&(1<<i))
        {
            if(cnt==0) lcm=arr[i];
            else lcm=lcm/gcd(lcm,arr[i])*arr[i];
            cnt++;
        }
        int ans=0;
        if(cnt%2) ans=n/lcm;
        else ans=-n/lcm;
        return ans;
    }
    int main()
    {
        while(cin>>n>>m)
        {
            n--;
            int a,cnt=0;
            for(int i=0;i<m;i++)
            {
                cin>>a;
                if(a!=0) arr[cnt++]=a;
            }
            long long ans=0;
            if(cnt<m) m=cnt;
            for(int i=1;i<(1<<m);i++)
            {
                ans+=solv(i);
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    /*
    13 4
    2 3 4 6
    
    */
  • 相关阅读:
    数组优化 Dijkstra 最短路
    F
    树 (p155, 从中序和后续回复二叉树)
    矩阵连乘 LRJ白书 p141 栈 解析表达式
    Train Problem II HDU 1023 卡特兰数
    codevs 1166 矩阵取数游戏
    BZOJ 2754: [SCOI2012]喵星球上的点名
    2017.6.11 校内模拟赛
    HDU 2896 病毒侵袭
    UvaLive 4670 Dominating Patterns
  • 原文地址:https://www.cnblogs.com/qijinbiao/p/2613862.html
Copyright © 2011-2022 走看看