题目描述

某人写了n封信和n个信封,如果所有的信都装错了信封。求所有信都装错信封共有多少种不同情况。

输入输出格式

输入格式:

一个信封数n

输出格式:

一个整数,代表有多少种情况。

输入输出样例

输入样例#1:
2

输出样例#1:
1

解题思路

这题就是裸的错排公式,D(n)=(n-1)*(D(n-1)+D(n-1)),代码如下

#include<stdio.h>
int main()
{
int d[]={,,,};//也不知道为什么0封信0个信封也有一种装错的情况……
int n;
scanf("%d",&n);
if(n<=)
{
printf("%d",d[n]);
return ;
}
for(int i=;i<=n;i++)
d[i]=(i-)*(d[i-]+d[i-]);
printf("%d",d[n]);
return ;
}

下面是转自百度百科的推导过程——

递推的推导错排公式

当n个编号元素放在n个编号位置,元素编号与位置编号各不对应的方法数用D(n)表示,那么D(n-1)就表示n-1个编号元素放在n-1个编号位置,各不对应的方法数,其它类推.
第一步,把第n个元素放在一个位置,比如位置k,一共有n-1种方法;
第二步,放编号为k的元素,这时有两种情况:⑴把它放到位置n,那么,对于剩下的n-1个元素,由于第k个元素放到了位置n,剩下n-2个元素就有D(n-2)种方法;⑵第k个元素不把它放到位置n,这时,对于这n-1个元素,有D(n-1)种方法;
综上得到
D(n) = (n-1) [D(n-2) + D(n-1)]
特殊地,D(1) = 0, D(2) = 1.
下面通过这个递推关系推导通项公式:
为方便起见,设D(k) = k! N(k), k = 1, 2, …, n,
则N(1) = 0, N(2) = 1/2.
n ≥ 3时,n! N(n) = (n-1) (n-1)! N(n-1) + (n-1)! N(n-2)
即 nN(n) = (n-1) N(n-1) + N(n-2)
于是有N(n) - N(n-1) = - [N(n-1) - N(n-2)] / n = (-1/n) [-1/(n-1)] [-1/(n-2)]…(-1/3) [N(2) - N(1)] = (-1)^n / n!.
因此
N(n-1) - N(n-2) = (-1)^(n-1) / (n-1)!,
N(2) - N(1) = (-1)^2 / 2!.
相加,可得
N(n) = (-1)^2/2! + … + (-1)^(n-1) / (n-1)! + (-1)^n/n!
因此
D(n) = n! [(-1)^2/2! + … + (-1)^(n-1)/(n-1)! + (-1)^n/n!].
此即错排公式。

容斥原理

编辑

用容斥原理也可以推出错排公式:
正整数1, 2, 3, ……, n的全排列有 n! 种,其中第k位是k的排列有 (n-1)! 种;当k分别取1, 2, 3, ……, n时,共有n*(n-1)!种排列是至少放对了一个的,由于所求的是错排的种数,所以应当减去这些排列;但是此时把同时有两个数不错排的排列多排除了一次,应补上;在补上时,把同时有三个数不错排的排列多补上了一次,应排除;……;继续这一过程,得到错排的排列种数为
D(n) = n! - n!/1! + n!/2! - n!/3! + … + (-1)^n*n!/n! = ∑(k=2~n) (-1)^k * n! / k!,
即D(n) = n! [1/0! - 1/1! + 1/2! - 1/3! + 1/4! + ... + (-1)^n/n!].
其中,∑表示连加符号,k=2~n是连加的范围;0! = 1,可以和1!相消。

简化公式

编辑

错排公式的原形为D(n) = n! (1/0! - 1/1! + 1/2! - 1/3! - ..... + (-1)^n/n!),当n很大时计算就很不方便。一个供参考的简化后的公式是D(n) = [n!/e+0.5] ,其中e是自然对数的底,[x]为x的整数部分。
证明:
由于1/e = e^(-1) = 1/0! - 1/1! + 1/2! - 1/3! - ..... + (-1)^n/n! + Rn(-1),
其中Rn(-1)是余项,等于(-1)^(n+1) * e^u / (n+1)!,且u∈(-1, 0).
所以,D(n) = n! * e^(-1) - (-1)^(n+1) * e^u / (n+1), u∈(-1, 0).
而|n! Rn| = |(-1)^(n+1) * e^u / (n+1)| = e^u / (n+1) ∈ (1/[e(n+1)], 1/(n+1)),可知即使在n=1时,该余项(的绝对值)也小于1/2。
因此,无论n! Rn是正是负,n! / e + 1/2的整数部分都一定与M(n)相同。

最新文章

  1. 学会给你的类(及成员)来定制一套自己的Attribute吧
  2. MS - 2 - 设计包含 min 函数的栈
  3. (C/C++) Callback Function 回调(diao)函数
  4. GAC(Global Assembly Cache)注册/卸载 dll
  5. 【转】Web标准中的常见问题
  6. CF 577C Vasya and Petya&#39;s Game
  7. IIS设置允许下载.exe文件解决方法(转)
  8. 监控持有sql和被堵塞的sql
  9. PNG文件格式具体解释
  10. [Oracle] 分析功能(1)- 语法
  11. ECOS- 技术问题答疑[转]
  12. springMVC源码分析--AbstractDetectingUrlHandlerMapping(五)
  13. centos6.6 minimal cannot found a valid baseurl for repo :base
  14. curl 错误总结
  15. Python request 在linux上持续并发发送HTTP请求遇到 Failed to establish a new connection: [Errno 11] Resource temporarily unavailable
  16. 2015 北京网络赛 C Protecting Homeless Cats hihoCoder 1229 树状数组
  17. Nginx技术研究系列6-配置详解
  18. 枚举 Java Enumeration接口
  19. 搞定queryString
  20. 【ASP.NET 进阶】PDF文件在线预览(类似百度文库)

热门文章

  1. Codeforces Round #281 (Div. 2) D. Vasya and Chess 博弈
  2. linux(centos)下安装git并上传代码些许步骤(亲自验证过的步骤)
  3. golang LMDB入门例子——尼玛,LMDB的文档真的是太少了
  4. 完美解决 linux sublime 中文无法输入
  5. DCloud-MUI:窗口管理
  6. PCB Windows远程桌面一键登录
  7. Android Gradle 学习笔记(七):Android Gradle 插件
  8. Redis(六)-数据类型
  9. Android检测代理
  10. 使用protobuf传递网络消息