在計數時,必須注意沒有重複,沒有遺漏
爲了使重疊部分不被重複計算,人們研究出一種新的計數方法
這種方法的基本思想是:先不考慮重疊的狀況,把包含於某內容中的全部對象的數目先計算出來,而後再把計數時重複計算的數目排斥出去,使得計算的結果既無遺漏又無重複
這種計數的方法稱爲容斥原理php
想必你們都不想讀這麼多字,並且讀了還不必定懂
因此咱們用維恩圖來看一下:
簡單明瞭,其實容斥原理就是小學學的重疊問題c++
在百度百科中所展示的式子是這樣的
spa
而對於像我這樣的初學者來看無疑是「天書」
因此我總結了一個式子
code
如圖,當咱們減去兩兩相交的部分時,三個部分都重合的那個被減去了三次
所以須要加上一次
其實容斥也就這麼多了
做爲Oier,固然咱們還要會敲代碼
找了一道模板題對象
HDU Eddy's愛好
代碼:blog
#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; }