1. 程式人生 > >容斥原理的公式推導

容斥原理的公式推導

對於容斥原理的最簡單的理解就是,把要計算的加上,然後把加多的減掉,然後再把減多的再加回去。這樣迴圈下去就對了。

一個好理解的例子就是一個班上有三個興趣班(c++,java,pasico),每個人都報了興趣班。30人報了一個,12人報了兩個,3人報了三個,求班上有多少人?這是一道小學題,自然也很簡單。ans=30-12+3=21(人)。然後這樣為什麼是對的呢?我們思考一下30之中把報了兩項的人計算了2次,把報了三項的人計算了3次。12中把報了3項的人計算了3次。所以我們用那個加減表示每種人都只計算1次的答案。(可以看圖再理解一下)

這裡寫圖片描述

但是並沒有那麼簡單,因為不可能每道題的係數都是-1和1的交替。要解決更一般性的問題,我們可能要自己推係數,我們重點講一下推係數的方法。

一般的,由總結的公式得出i=1ns(Ci)fi=s(C0),其中s(Ci)表示所有物品在滿足Ci情況下的總貢獻(一般的計數問題s(Ci) 就是 滿足條件Ci 情況的個數),而fi是一個係數,在計算時,我們才能把除答案以外的的貢獻消掉。(這是用於計算答案的式子)要對這個公式有一個理解,我們還是舉兩個例子。

一、(錯排問題),一串1n的數列,求對於任意i不在第i位排列的方案數。

對於這個問題,首先我們要構造Ci,當然這是很簡單的,我們很容易就可以想到:Ci表示滿足有至少i個不錯排數的情況。所以有:

i=0nCnifi==[n==0]。反正第一次看人家推這個式子是懵逼的,為啥s(Ci)變成一個組合數了呢?其實仔細推敲一下還是可以理解的。首先,上面的式子和下面是有區別的。也就是說,這倆貨都不是一個東西。這個式子是用來計算fi的!!!

現在大概能懂了吧,假設有一個恰好有n個不錯排數的情況,它在i=0時被計算了Cn0次,在i=1時被計算了Cn1次,以此類推……因為我們要求的的是錯排數列,所以當n0時是不符合題意的,我們要讓它的貢獻為0(另:只有n=0時,這個排列的貢獻為1)。然後可以想到一個n2遞推fi的方法。當然這類

fi是有規律的,我們打表可知:fi=(1)i

至此我們把fi全部計算出來了,之後我們怎麼計算答案呢?這個時候我們就可以使用上面一個公式了。ans=i=1nCni(ni)!fi

是不是很神奇呢?

二、(約數問題),給定m個數,統計在[1,n]中,有奇數個整除它的數的個數。(i屬於[1,n],若在這m個數裡,有奇數個數可以整除i,則ans++),m15n1e9

列舉n的複雜度是nm的,顯然會超時,考慮容斥。

列舉