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

    两个集合的容斥关系公式:A∪B = A+B - A∩B

    三个集合的容斥关系公式:A∪B∪C = A+B+C - A∩B - B∩C - C∩A +A∩B∩C

    四个集合的容斥关系公式:A∪B∪C∪D = |A|+|B|+|C|+|D| - |A∩B| - |A∩C| - |A∩D|- |B∩C| - |B∩D| - |C∩D|
    +|A∩B∩C|+|A∩B∩D| +|A∩C∩D| +|B∩C∩D| - |A∩B∩C∩D|

    n个集合的容斥关系公式:|A1∪A2∪A3∪…∪An| = ∑|Ai1|-∑|Ai1∪Ai2|+…+(-1)^(k+1)∑|Ai1∪Ai2∪…∪Aik|

    +…+(-1)^(n+1)∑|A1∪A2∪…∪An| 

    应用

    1. 求10000以内不能被 2 3 5 整出的数

    ans = n/2 + n/3 + n/5 + n/6 + n/10 + n/15 + n/30;

    答案 = 10000 - ans 

    2. n封信对应n个信封,求恰好全部装错了信封的方案数 

    先讲一下全错排算法

    要装第i封信的时候,先把前i-1个信全装错信封,然后随便选其中一个与第i封信交换,有i-1种选法

    那么dp[i] = (i-1) * dp[i-1]

    但是还有一种情况

    要装第i封信的时候,先从i-1封信中任选i-2个信把他们全装错信封,然后把剩下的那个信与第i个交换,从i-1封信中任选i-2个信有i-1种选法

    那么dp[i] = (i-1) * dp[i-2]

    两个式子联合起来就是个递归的式子dp[i] = (i-1) * (dp[i-1] + dp[i-2])

    然后讲一下容斥算法

    首先,所有装信的总数是n!

    A1表示1封信装对信封,数量是(n-1)! (只有n-1个位置可以乱放)

    A2表示2封信装对信封,数量是(n-2)! (只有n-2个位置可以乱放)

    ...

    An表示n封信装对信封,数量是1 

    那么这题的答案就是

    n! - C(n, 1)*|A1| + C(n, 2)*|A2| - C(n, 3)*|A3| + ... + (-1)^n * C(n, n)*|A4|

    化简

    n! - n! / 1! + n! / 2! - n! / 3! + ... + (-1)^n * n! / n!

    提取n!

    n!(1 - 1/1! + 1/2! - 1/3! + ... + (-1)^n * 1/n!)

    3.给花盆涂色

    给n盆花涂色,从m种颜色中选取k种颜色涂,保证正好用上k种颜色,你必须用上这k种颜色去涂满n个相邻的花,并且要求相邻花的颜色不同,求方案数。

     (1 ≤ n, m ≤ 1e9 , 1 ≤ k ≤ 1e6 , k ≤ n, m)

    首先,用k种颜色涂花,假如不考虑全部用上,那么总的方案数是多少

    第一盆花有k种颜色选择,之后的花因为不能跟前一盆花的颜色相同,所以有k-1种选择

    于是总方案数为k*(k-1)^(n-1)

    因为题目问必须用上k种颜色

    这里面包含了只用k-1种颜色的情况,应该减掉所有用k-1种的情况

    减掉的东西里面,这里面包含了只用k-2种颜色的情况,应该加回来...

    反反复复,最后就得出答案了

    4.求(a,b)区间与n互质的数的个数

    我们可以先求(1~b)区间的答案,然后减去(1~a-1)区间的答案

    这样问题就转换为(1~m)区间与n互质的数的个数

    互质的不好求,我们可以求不互质的个数,然后减一下

    所有我们先求出n的所有质因数,然后用容斥做

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    vector<ll> p;
    vector<ll>::iterator it;
    vector<ll> v;
    void init(ll x)
    {
        p.clear();
        for(ll i =2;i*i<=x;i++)
        {
            if(x%i == 0){
                p.push_back(i);
                while(x%i == 0)
                    x /= i;
            }
        }
        if(x>1)
            p.push_back(x);
        int v_size;
        v.clear();
        for(int i=0;i<p.size() ;i++)
        {
            v_size = v.size();
            for(int j=0;j<v_size;j++)
            {
                v.push_back(v[j] * p[i]);
            }
            v.push_back(p[i]);
        }
    }
    ll work(ll x)
    {
        ll ans = x,flag = -1;
        for(int i=0;i<v.size();i++)
        {
            ans += flag*x/v[i];
            flag = -flag;
        }
        return ans;
    }
    int main()
    {
        int t;
        ll l,r,n;
        cin>>t;
        while(t--)
        {
            cin>>l>>r>>n;
            init(n);
            cout<<work(r) - work(l-1)<<endl;
        }
        return 0;
    }
  • 相关阅读:
    C# Mongo Client 2.4.2创建索引
    MongoDB Driver:使用正确的姿势连接复制集
    C# Mongo Client 2.4.2判断是否存在表
    c# Mongodb批量更新
    c# Mongodb创建自增列
    class A where T:new()是什么意思
    Dapper Extensions中修改Dialect
    golang 中的 sizeof 以及 golang中的 union
    将c语言的结构体定义变成对应的golang语言的结构体定义,并将golang语言结构体变量的指针传递给c语言,cast C struct to Go struct
    golang 与 c语言 之间传递指针的规则提案
  • 原文地址:https://www.cnblogs.com/tonyyy/p/10649896.html
Copyright © 2011-2022 走看看