先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乙個二維字首和詳解
不懂二維字首和的可以看看。
容斥原理及證明
設共有 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,因為在並集中只計...
容斥原理及廣義容斥(二項式反演)
就是這麼乙個公式 因為本人太弱,不會嚴謹的數學證明,感性理解一下就是把那些重複的元素去掉就行了。容斥的套路挺多的,還是要多做題。貌似也叫二項式反演,總共有3種形式,但常用的只有兩種 1.若 f n sum limits binomg i 那麼 g n sum limits 1 binomf i 具體...
zoj 3614 二維RMQ 容斥
rmq求出矩陣區間最大,陣列sum和pro分別存座標i,j到右下角的矩陣所有元素和,和平方和,然後根據容斥求出某一矩陣的元素和,平方和。然後根據方差展開求最大座標,就ok啦。include include include include include include include include...