错排,意思就是原来有一个n个元素的排列,现在要打乱它们的顺序,使每个元素都不在原来的位置,一共有多少种可能。
因为刚开始接触的时候没听懂,然后看一个例子后才理解的差不多的,所以我就按放书这个例子来谈下。
首先,假设有n本书,我们取一本书,书的编号为m,同时这本书位置也是m,现在,我不能把书放到位置m,只能在剩下的n-1个位置中选择一个位置,所以错排操作数有D(n-1)种,现在我们假设将书放在位置k,那么位置k上的书我们就要拿出来,所以现在我们又要讲书k放到其他位置上,而现在问题来了,因为位置m是空的,所以我们有两种选择, 第一 :将书k放到位置m上,这样的话就相当于交换了k和m的位置,那么,还剩下n-2个位置,就相当于回到原点,重新取书再排列,此时求n-2本的错排操作数D(n-2),结合第一步,有n-1*(D(n-2))种方法。 第二 :不将书k放到位置吗m上,我们还要将手里这本和剩下的n-2本,也就是n-1本,同时又要求手里这本k还不能放到位置m,这就相当于把手里这本加上剩下的n-2本也就是n-1本书进行错排,所以有n-1*(D(n-1))种方法。综合这两种情况,最后结果就是n-1*(D(n-2)+D(n-1));
话不多数,上题!!!
国庆期间,省城HZ刚刚举行了一场盛大的集体婚礼,为了使婚礼进行的丰富一些,司仪临时想出了有一个有意思的节目,叫做"考新郎",具体的操作是这样的:
首先,给每位新娘打扮得几乎一模一样,并盖上大大的红盖头随机坐成一排;
然后,让各位新郎寻找自己的新娘.每人只准找一个,并且不允许多人找一个.
最后,揭开盖头,如果找错了对象就要当众跪搓衣板...
看来做新郎也不是容易的,假设一共有N对新婚夫妇,其中有M个新郎找错了新娘,求发生这种情况一共有多少种可能.
Input
输入数据的第一行是一个整数C,表示测试实例的个数,然后是C行数据,每行包含两个整数N和M(1<M<=N<=20)。
Output
对于每个测试实例,请输出一共有多少种发生这种情况的可能,每个实例的输出占一行。
Sample Input
2 2 2 3 2
Sample Output
1 3
#include <bits/stdc++.h> using namespace std; int main() { long long fact[30],num[30]; int i,n,m,t; scanf("%d",&t); num[1]=0; num[2]=1; fact[0]=1; fact[1]=1; fact[2]=2; for(i=3; i<25; i++) { num[i] = (i-1)*(num[i-1]+num[i-2]); } for(i=3; i<25; i++) { fact[i] = fact[i-1]*i; } while(t--){ scanf("%d%d",&n,&m); printf("%lld ",num[m]*(fact[n]/fact[m]/fact[n-m])); } return 0; }
以上表述若有错误,欢迎批评指正。。。。。(当然,我也不一定改。、。、)