有n个集合,求这n集合的并集。
方法:容斥原理
公式:S1 ⋃ \bigcup ⋃ S2 ⋃ \bigcup ⋃ S3 ⋃ \bigcup ⋃ … ⋃ \bigcup ⋃ Sn = C n 1 C_{n}^{1} Cn1 - C n 2 C_{n}^{2} Cn2 + C n 3 C_{n}^{3} Cn3 - C n 4 C_{n}^{4} Cn4 … (-1)(n-1) C n n C_{n}^{n} Cnn
共2n- 1项( 二项式定理 ( 1 + 1 )n - C n 0 C_{n}^{0} Cn0 展开式 )
例:有三个集合
S1 = { 1, 2, 3, 4 },S2 = { 2, 3, 4, 5 },S3 = { 3, 4, 5, 6 }
C 3 1 C_{3}^{1} C31 : S1 , S2 , S3
C 3 2 C_{3}^{2} C32 : S1 ⋂ \bigcap ⋂ S2 = { 2, 3, 4 } ,S1 ⋂ \bigcap ⋂ S3 = { 3, 4 } , S2 ⋂ \bigcap ⋂ S3 = { 3, 4, 5 }
C 3 3 C_{3}^{3} C33 : S1 ⋂ \bigcap ⋂ S2 ⋂ \bigcap ⋂ S3 = { 3,4 }
S1 ⋃ \bigcup ⋃ S2 ⋃ \bigcup ⋃ S3 = S1 + S2 + S3 - S1 ⋂ \bigcap ⋂ S2 - S2 ⋂ \bigcap ⋂ S3 - S1 ⋂ \bigcap ⋂ S3 + S1 ⋂ \bigcap ⋂ S2 ⋂ \bigcap ⋂ S3 = { 1, 2, 3, 4, 5, 6 }
实现方式
用代码实现集合方式可以利用二进制。
0表示不选,1表示选择,多少个集合二进制就多少位。
由上例:二进制011表示选择集合 S1 S2 不选 S3
C 3 1 C_{3}^{1} C31 :001( S1 ) ,010( S2 ) ,100( S3 )
C 3 2 C_{3}^{2} C32:011( S1 ⋂ \bigcap ⋂ S2 ) ,101( S1 ⋂ \bigcap ⋂ S3 ) ,110( S2 ⋂ \bigcap ⋂ S3 )
C 3 3 C_{3}^{3} C33:111( S1 ⋂ \bigcap ⋂ S2 ⋂ \bigcap ⋂ S3 )
可以观察到全部为1到111(23- 1的二进制)中的项。
总结:所有组合情况均可由1到2n- 1的二进制数表示。
代码实现
// 从1枚举到1111(m个1)每个1位置对应着一个集合(最少一个集合)
for (int i = 1; i < 1 << m; i++)
{
for (int j = 0; j < m; j++) // 枚举每一位
{
if (i >> j & 1) // 该位二进制对应的值
{
operation(); //对集合操作
}
}
}