hdu 2049 不容易系列之(4)——考新郎 解题报告
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2049
写这篇解题报告时 我真的很气愤 对自己又一次犯下低级错误改了两个小时 int型的数据居然用%I64d输出 错了还找不出来 然后就各种试C/C++的输出 对自己都无语了 也是对自己最近没A题的教训吧
这个题使我感受到了数学对于ACM的重要性 可恶上学期高数居然挂了 太颓废了
排列组合知识 对于n个数取m个数(不及顺序)的取法为 n!/( (n-m)!*m!). 当时打的时候没考虑清楚 没想到直接打地推公式 就是用一个数组存储阶乘(要是用递归会超时)
然后用乘除计算
关于错排:
给定m个数进行全错排 只有两种情况
① 前m-1个已经全部错排完毕 第m个数只需和m-1个数的其中一个交换
②前m-2个已经全部错排完毕 而第m-1个是正确的 第m个数需要和m-1交换 第m-1个数 有m-1中选择
因此 g[m]=(m-1)*g[m-1]+(m-1)*g[m-2].
这个题目就是n个人里面选出m个人进行错排 输出排列数 使用乘法原理即可
即m个人错排数*从n中选出m个人的排列数
代码如下
1 #include<iostream>
2 #include<cstdio>
3 using namespace std;
4 int main()
5 {
6 int i,j,k,ncase,n,m;
7 long long f[25],g[25],ans;
8 f[0]=1;
9 for(i=1;i<=25;i++)
10 {
11 f[i]=f[i-1]*i;
12 }
13
14 g[1]=0;
15 g[2]=1;
16 for(i=3;i<=25;i++)
17 {
18 g[i]=(i-1)*(g[i-1]+g[i-2]);
19 }
20
21 cin>>ncase;
22 for(i=0;i<ncase;i++)
23 {
24 cin>>n>>m;
25 ans=g[m]*( f[n]/f[n-m]/f[m] );
26 cout<<ans<<endl;
27
28 }
29
30 // system("pause");
31 return 0;
32 }