acwing算法基础之数学知识--容斥原理

目录

  • 1 基础知识
  • 2 模板
  • 3 工程化

1 基础知识

题目描述:给定整数n和m个不同的质数,p1,p2,…pm,求1~n中能被这m个质数中至少一个质数整除的数有多少个。其中n和 p i p_i pi 1 0 9 10^9 109以内,而m在16以内。

容斥原理:
有两个集合 A A A B B B,求总和 ∣ A ∪ B ∣ |A\cup B| AB,答案为
∣ A ∪ B ∣ = ∣ A ∣ + ∣ B ∣ − ∣ A ∩ B ∣ |A\cup B|=|A| +|B| - |A\cap B| AB=A+BAB
有三个集合 A A A B B B C C C,求总和 ∣ A ∪ B ∪ C ∣ |A\cup B\cup C| ABC,答案为
∣ A ∪ B ∪ C ∣ = ∣ A ∣ + ∣ B ∣ + ∣ C ∣ − ∣ A ∩ B ∣ − ∣ A ∩ C ∣ − ∣ B ∩ C ∣ + ∣ A ∩ B ∩ C ∣ |A\cup B \cup C|=|A|+|B|+|C|-|A\cap B|-|A\cap C|-|B\cap C|+|A\cap B \cap C| ABC=A+B+CABACBC+ABC

进一步抽象,
某个类有 n n n中不同的属性,记为 P i P_i Pi(其中 i = 1 , 2 ⋯ n i=1,2\cdots n i=1,2n),拥有属性 P i P_i Pi的对象构成集合 S i S_i Si,那么对象总和为,
∣ ∪ i = 1 n S i ∣ = ∑ i ∣ S i ∣ − ∑ i < j ∣ S i ∩ S j ∣ + ∑ i < j < k ∣ S i ∩ S j ∩ S k ∣ − ⋯ + ( − 1 ) n − 1 ∣ S 1 ∩ S 2 ⋯ ∩ S n ∣ |\cup_{i=1}^{n} S_i|=\sum_{i}|S_i|-\sum_{ii=1nSi=iSii<jSiSj+i<j<kSiSjSk+(1)n1S1S2Sn
上式即为容斥原理。

解题思路:用容斥原理进行求解,且利用二进制表示中的1表示第i个质数选不选,以此计算出每一项。
C++代码如下,

#include 

using namespace std;

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

int main() {
    cin >> n >> m;
    for (int i = 0; i < m; ++i) cin >> p[i];
    
    int res = 0;
    for (int i = 1; i < 1 << m; ++i) {
        int t = 1;
        int cnt = 0;
        for (int j = 0; j < m; ++j) {
            if (i >> j & 1) {
                cnt += 1;
                if ((long long)t * p[j] > n) {
                    t = -1;
                    break;
                }
                t = (long long)t * p[j];
            }
        }
        if (t != -1) {
            if (cnt % 2 == 1) {
                res += n / t;
            } else {
                res -= n / t;
            }
        }
    }
    cout << res << endl;
    return 0;
}

2 模板

暂无。。。

3 工程化

暂无。。。

你可能感兴趣的:(Acwing,C++学习,算法,c++)