此博客链接:https://www.cnblogs.com/ping2yingshi/p/12457266.html
不容易系列之(4)——考新郎(87min)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2049
Problem Description
国庆期间,省城HZ刚刚举行了一场盛大的集体婚礼,为了使婚礼进行的丰富一些,司仪临时想出了有一个有意思的节目,叫做"考新郎",具体的操作是这样的:
首先,给每位新娘打扮得几乎一模一样,并盖上大大的红盖头随机坐成一排;
然后,让各位新郎寻找自己的新娘.每人只准找一个,并且不允许多人找一个.
最后,揭开盖头,如果找错了对象就要当众跪搓衣板...
看来做新郎也不是容易的事情...
假设一共有N对新婚夫妇,其中有M个新郎找错了新娘,求发生这种情况一共有多少种可能.
首先,给每位新娘打扮得几乎一模一样,并盖上大大的红盖头随机坐成一排;
然后,让各位新郎寻找自己的新娘.每人只准找一个,并且不允许多人找一个.
最后,揭开盖头,如果找错了对象就要当众跪搓衣板...
看来做新郎也不是容易的事情...
假设一共有N对新婚夫妇,其中有M个新郎找错了新娘,求发生这种情况一共有多少种可能.
Input
输入数据的第一行是一个整数C,表示测试实例的个数,然后是C行数据,每行包含两个整数N和M(1<M<=N<=20)。
Output
对于每个测试实例,请输出一共有多少种发生这种情况的可能,每个实例的输出占一行。
Sample Input
2
2 2
3 2
Sample Output
1
3
题解:
方法:全排错组合和排列组合。
全排错组合:
-
当n=1时,全排列只有一种,不是错排,D1= 0。
-
当n=2时,全排列有两种,即1、2和2、1,后者是错排,D2= 1。
-
当n=3时,全排列有六种,即1、2、3;1、3、2;2、1、3;2、3、1;3、1、2;3、2、1,其中只有有3、1、2和2、3、1是错排,D3=2。用同样的方法可以知道D4=9。
-
最小的几个错排数是:D1= 0,D2= 1,D3=2,D4= 9,D5= 44,D6= 265,D7= 1854.
-
具体推导过程可以参考百度百科,链接:https://baike.baidu.com/item/%E5%85%A8%E9%94%99%E4%BD%8D%E6%8E%92%E5%88%97/6806416?fr=aladdin全错排公式:D(n)=(n-1)*(D(n-1)+D(n-2))
思路:本题给了n个新郎,m个选错的新郎,那么有n-m个找对的新郎,对于选错m的新郎用全排错公式,算出有多少种选错的可能,对于选对n-m的新郎全排列,算出有多少种选对的可能,选对的可能乘以选错的可能即为n个新郎,m个选错的新郎的可能。
注意:1.求排列组合数时注意算出的结果可能比较大,考虑使用long数据类型。
2.全排错的结果可能也是非常大的,所以在定义数组时也需要考虑数组的数据类型。
代码如下:
import java.util.Scanner; public class Main { public static void main(String[] args) { // TODO Auto-generated method stub Scanner scan=new Scanner(System.in); long []arr=new long [22]; arr[0]=0; arr[1]=0; arr[2]=1; long sum1; long sum2; long sum; long result; for(int i=3;i<=20;i++)//全排错 { arr[i]=(arr[i-1]+arr[i-2])*(i-1); } int C=scan.nextInt(); while(C>0) { sum1=sum2=1; int n=scan.nextInt();//新郎总数 int m=scan.nextInt();//选错新郎数 for(int j=1;j<=m;j++) { sum1*=j; } for(int k=n-m+1;k<=n;k++) { sum2*=k; } sum=sum2/sum1; result=sum*arr[m]; System.out.println(result); C--; } } }