错排公式的证明与实现

  所谓错排公式就是说给你一个序列,这个序列有n个数,然后要求这个序列的排列中有几个满足每个元素都不在原来的位置。这个是直接有一个地推关系的:f[n]=(n-1)*(f[n-1]+f[n-2])。证明如下:

  首先我们知道f[1]=0,f[2]=1.然后当n大于等于三的时候我们考虑他们之间的关系。将各个元素标号为1到n。那么我们考虑第n个元素,它的能力在于是将自己与前面的一个换位置,也就是说它的前面可以是已经完成的错排或者是有一个元素没有错排。那么有两种情况:

1、前面有一个元素在本身的位置,这时最后一个元素必须选择同他交换。没装错的可能是任意的一个,也就是有(n-1)*f[n-2]种

2、前面的已经排好了,这是最后一个可以随意交换,也就是(n-1)*f[n-1]

代码很简单,用递归写,但是还是贴一下吧

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<queue>
 5 #include<cstring>
 6 #include<cmath>
 7 using namespace std;
 8 long long f[95];
 9 int main()
10 {
11     f[1]=0;
12     f[2]=1;
13     for(int i=3;i<=20;i++){
14         f[i]=(f[i-1]+f[i-2])*(i-1);
15     }
16     int n;
17     while(scanf("%d",&n)==1){
18         printf("%lld\n",f[n]);
19     }
20     return 0;
21 }

   另外错排还有一个通项公式 f(n) = n![1-1/1!+1/2!-1/3!+……+(-1)^n*1/n!]。这个公式有两个解释,首先是它可以从递归式直接推出来;第二种方法是采用容斥定理证明。这里不赘述了。

转载于:https://www.cnblogs.com/MrLJC/p/3460604.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值