容斥原理

容斥原理

定義

在計數時,必須注意沒有重複,沒有遺漏
爲了使重疊部分不被重複計算,人們研究出一種新的計數方法
這種方法的基本思想是:先不考慮重疊的情況,把包含於某內容中的所有對象的數目先計算出來,然後再把計數時重複計算的數目排斥出去,使得計算的結果既無遺漏又無重複
這種計數的方法稱爲容斥原理

想必大家都不想讀這麼多字,而且讀了還不一定懂
所以我們用維恩圖來看一下:
TIM圖片20190409201712.png
簡單明瞭,其實容斥原理就是小學學的重疊問題

公式

在百度百科中所展現的式子是這樣的
TIM圖片20190409201730.png

而對於像我這樣的初學者來看無疑是“天書”
所以我總結了一個式子
TIM圖片20190409201742.png

公式含義

如圖,當我們減去兩兩相交的部分時,三個部分都重合的那個被減去了三次
因此需要加上一次
其實容斥也就這麼多了
作爲Oier,當然我們還要會敲代碼
找了一道模板題

HDU Eddy's愛好
代碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int prime[18]= {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59};
LL res, n;
int a[5];
void dfs(int cur, int num, int cnt, LL sum) { // 從素數表cur位置開始,當前一共num個,需要cnt個,當前素數乘積爲sum
    if (num == cnt) {
        LL temp = (LL) pow(n + 0.5, 1.0 / sum);
        if (temp > 1) res += temp - 1; // 減去1的情況
        return;
    }
    for (int i = cur; i < 17; i++) {
        if (sum * prime[i] < 60) dfs(i + 1, num + 1, cnt, sum * prime[i]);//如果素數沒到60,則這個素數可以取
        else dfs(i + 1, num, cnt, sum);// 否則跳過該數
    }
}
int main() {
    while (scanf("%d", &n) != EOF) {
        LL sum = 0;
        for (int i = 1; i <= 3; i++) {
            res = 0;
            dfs(0, 0, i, 1);
            if (i & 1) sum += res;
            else sum -= res;
        }
        printf("%d\n", sum + 1);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章