算法学习笔记(41)——容斥原理

容斥原理

S1,S2,,Sn 为有限集合,|S| 表示集合 S 的大小,则:

|i=1nSi|=i=1n|Si|1ijn|SjSj|+1ijkn|SjSjSk|++(1)n+1|S1Sn|

可以用文氏图来宏观地描述容斥原理,如下图所示:
img

组合数的性质:

Cn0+Cn1+Cn2++Cnn=2n

从n个数里面挑0个数的方案数,加上挑1个数的方案数...,一直加到挑n个数的方案数,等价于从n个数中选任意多个数,每个数都是挑或不挑的所有方案数。
所以 Cn1+Cn2++Cnn=2n1,共有 2n1 项,时间复杂度为 O(2n)

题目链接:AcWing 890. 能被整除的数

  1. 每个集合实际上并不需要知道具体元素是什么,只要知道这个集合的大小,大小为|Si|=npi
  2. 交集的大小如何确定?因为 pi 均为质数,这些质数的乘积就是他们的最小公倍数,n 除这个最小公倍数就是交集的大小,故 |S1S2|=np1p2
  3. 如何用代码表示每个集合的状态?这里使用的二进制,位运算枚举所有方案,从 1 枚举到 2n1,用每一个数代表一种选法(二进制形式)。以 m=4 为例,所以需要 4 个二进制位来表示每一个集合选中与不选的状态,1101m=4 ,这里表示选中集合 S1,S3,S4 ,故这个集合中元素的个数为 np1p3p4, 因为集合个数是 3 个,根据公式,前面的系数为 (1)31=1。所以到当前这个状态时,应该是 res=res+np1p3p4 。这样就可以表示的范围从 00001111 的每一个状态

用二进制表示状态的小技巧非常常用,后面的状态压缩DP也用到了这个技巧,因此一定要掌握

C++程序1s内可以计算 107 ~ 108 次,本题中 2m=216=65536,不会超时。
1np 的倍数的个数是 np

时间复杂度:O(m2m)=O(16×216)1,000,000

#include <iostream>

using namespace std;

typedef long long LL;

const int N = 20;
int n, m;
int primes[N];

int main()
{
    cin >> n >> m;
    for (int i = 0; i < m; i ++ ) cin >> primes[i];
    
    int res = 0;    //  用于存储结果(满足条件的整数个数)
    
    // 枚举从1到2^n - 1(111...1)的数,代表所有的选择方案
    for (int i = 1; i < 1 << m; i ++ ) {
        int t = 1;  // 存储当前选择方案里的质数的乘积
        int s = 0;  // 存储选中的方案的数量,根据奇偶决定正负号
        
        // 枚举当前方案的每一位,1表示当前方案选择了当前位的数字,0表示没有选择
        for (int j = 0; j < m; j ++ ) {
            // 如果当前为数字是1,代表选择了该数字
            if (i >> j & 1) {
                // 乘积大于n,则 n/p[0]*...*p[j] = 0,则n被分母的几个质数整除的交集大小是0
                if ((LL)t * primes[j] > n) {
                    t = -1; // 标记当前方案不符合,跳出循环,判断下一方案
                    break;
                }
                s ++;       // 统计当前方案内的数字个数
                t *= primes[j];
            }
        }
        
        if (t == -1) continue;
        
        // 二进制末尾是1则为奇数,等价于s % 2 != 0
        if (s & 1) res += n / t;
        else res -= n / t;
    }
    
    cout << res << endl;
    
    return 0;
}
posted @   S!no  阅读(132)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示