容斥原理及二維字首和

2022-08-05 13:09:18 字數 1960 閱讀 1960

先mk一個容斥原理詳解

容斥原理大概就是 :

要計算幾個集合並集的大小,我們要先將所有單個集合的大小計算出來,然後減去所有兩個集合相交的部分,再加回所有三個集合相交的部分,再減去所有四個集合相交的部分,依此類推,一直計算到所有集合相交的部分。

引用葉學長的例子:

a和b出現至少一人的概率(或方案數等)=a出現的概率+b出現的概率-兩人同時出現的概率。a和b都不出現的概率=1-至少出現一人的概率,然後再容斥算後面那個東西。n個a全部鴿鴿的概率=1-至少鴿一個的概率+至少鴿兩個的概率-......=1-至少鴿奇數個的概率+至少鴿偶數個的概率。

考試時如果感覺有點策不清就畫圖吧。。。韋恩圖是特別重要的解題手段

證明看容斥原理詳解

p1450 [haoi2008]硬幣購物

硬幣購物一共有4種硬幣。面值分別為c1,c2,c3,c4。某人去商店買東西,去了tot次。每次帶di枚ci硬幣,買s的價值的東西。請問每次有多少種付款方法。

其中注意資料範圍di,s<=100000,tot<=1000。

本題如何用容斥原理:

引用題解的話:

簡單來說,就是把重複計算的部分去掉,把多去掉的部分加回來

針對本題而言,就是:

不合法數目=1超出的部分+2超出的部分+……1,2共同超出的部分-2,3共同超出的部分……+1,2,3共同超出的部分……(後面以此類推)

**實現就比較容易了

#includeusing namespace std;

#define int long long //這道題不開long long會爆int

int t,k,n,m;

int s;

int ans=0;

int f[100005],c[5],d[5];//f[i]為預處理的完全揹包

inline int read() //快讀

inline void work()

inline void dfs(int now,int s,int b)

//剪枝

dfs(now+1,s,b);//求合法的部分

dfs(now+1,s-(d[now]+1)*c[now],-b);//求不合法的部分,b要變號所以乘以-1;

} signed main()

return 0;

}

總結思路

先預處理f[i]表示在不限制硬幣數量的情況下購買價值為i的物品的方案數。於是我們可以跑一個完全揹包。

對於硬幣個數的限制,考慮容斥:欽定若干種硬幣使用di+1次,也就是欽定它超過限制。設被欽定的總費用為x,方案數就是f[s-x]。容斥一下,偶加奇減。

具體證明為畫圖,直觀的表現出容斥原理的思想。

二維字首和,有效減少查詢統計時的複雜度,每一次查詢o(n)o(n)降到o(1),絕對過的了

記住:上加左,減左上,加自己

ans[i][j]=ans[i][j-1]+ans[i-1][j]-ans[i-1][j-1];

p2822 組合數問題

優化之後的**

#includeusing namespace std;

int t,k,n,m;

long long c[2005][2005],ans[2005][2005];//ans表示二維字首和

inline void work()

ans[i][i+1]=ans[i][i];

}

}inline int read()

int main()

return 0;

}

mk一個二維字首和詳解

不懂二維字首和的可以看看。

容斥原理及廣義容斥(二項式反演)

就是這麼一個公式 因為本人太弱,不會嚴謹的數學證明,感性理解一下就是把那些重複的元素去掉就行了。 容斥的套路挺多的,還是要多做題。。。 貌似也叫二項式反演,總共有3種形式,但常用的只有兩種 1 若 f n sum limits binomg i 那麼 g n sum limits 1 binomf ...

容斥原理及證明

設共有 n 個集合, a i 表示第 i 個集合,則所有集合的並集可表示成以下形式 a 1 cup a 2 cup cdots cup a n sum n 1 sum a 1 cap a 2 cap cdots cap a i 設某個元素被 x 個集合包含,顯然地,其對左式的貢獻為1,因為在並集中只...

容斥原理的二進位制實現模版

最近學習容斥原理,實現容斥原理大致有三種方法 dfs,佇列陣列,二進位制。 今天主要講下二進位制實現容斥原理 有一個集合,求集合的子集?很顯然答案為 也就是2 n個,也就是每一個子集有唯一標誌符 i 0 看下面的 1 include2 include3 include4 include5 include...