容斥原理我初中就听老师说过了,不知道你们有没有听过(/≧▽≦)/

 

百度百科说:

在计数时,必须注意没有重复,没有遗漏。

为了使重叠部分不被重复计算,人们研究出一种新的计数方法。

这种方法的基本思想是:先不考虑重叠的情况,把包含于某内容中的所有对象的数目先计算出来,然后再把计数时重复计算的数目排斥出去,使得计算的结果既无遗漏又无重复。

这种计数的方法称为容斥原理。

 

 

好标准的说法(#-.-)

 

 

那我举个简单的例子

 

两个集合的容斥原理: 设A, B是两个有限集合

数论14——容斥原理

那么

|A + B| = |A| + |B| - |AB|

|A|表示A集合中的元素个数

 

三个集合的容斥原理: 设A, B, C是三个有限集合

数论14——容斥原理

那么

|A + B + C| = |A| + |B| + |C| - |AB| - |AC| - |BC| + |ABC|

 

 

 

 

这就叫容斥原理

 

 

 

 

 

接下来直接做例题了

 

 

 

 

 

 

全错排(装错信封问题)

hdu 1465

http://acm.hdu.edu.cn/showproblem.php?pid=1465

 

n封信对应n个信封

求恰好全部装错了信封的方案数

 

本来全错排是有自己的一个公式的,叫全错排公式(跟容斥没关系)

那我顺便来讲讲全错排( >ω<)

要装第i封信的时候,先把前i-1个信全装错信封,然后随便选其中一个与第i封信交换,有i-1种选法

那么dp[i] = (i-1) * dp[i-1]

但是还有一种情况

要装第i封信的时候,先从i-1封信中任选i-2个信把他们全装错信封,然后把剩下的那个信与第i个交换,从i-1封信中任选i-2个信有i-1种选法

那么dp[i] = (i-1) * dp[i-2]

两个式子联合起来

就是那么dp[i] = (i-1) * (dp[i-1] + dp[i-2])

这就是全错排公式,递推,递归都可以做

 

全错排递推AC代码:

#include<cstdio>
typedef long long LL;
int n;
LL dp[25];
void init(){
    dp[1] = 0;
    dp[2] = 1;
    for(int i = 3; i <= 20; i ++){
        dp[i] = (i-1) * (dp[i-1] + dp[i-2]);
    }
}
int main(){
    init();
    while(~scanf("%d", &n)){
        printf("%I64d\n", dp[n]);
    }
}
View Code

相关文章:

猜你喜欢
  • 2022-12-23
  • 2022-01-24
  • 2021-07-02
  • 2022-12-23
  • 2021-10-07
  • 2022-12-23
  • 2021-07-12
相关资源
相似解决方案