题目:HDU-2049
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2049
题目:
2 2 2 3 2
1 3
f(n)=(f(n-1)+f(n-2))*(n-1);
f(1)=0;
f(2)=1;
这道题是n个人,错了m个,那我们就转化为m个人全错排好了,那n-m个人坐对了,m个人全错排,n-m个人坐对的方式有c(m,n-m)(组合数)种,那n个人m个人坐对的种数就是c(m,n-m)*f(m),当然,有几个特殊情况需要另外讨论。比如说n=m时,组合数计算需要返回一个1,结果就是f(m),还有m=1时,f(1)=0,计算结果是0,而事实上计算结果是c(n,1)种,所以我们在计算完f(i)的值以后可以把f(1)赋为1,(因为1<m<=n<=20,所以不用考虑用到f(1)计算结果不正确),那就可以解决这道题目啦~
#include<iostream> #include<cstring> #include<algorithm> #include<cstdio> #include<math.h> using namespace std; long long ans[25]; int a,b,t; long long c(int m,int n){ if(n==0) return 1; //需要注意加上c(n,0)=1 if(m==n) return 1; if(n==1) return m; else return c(m-1,n-1)+c(m-1,n); } int main(){ ans[1]=0;ans[2]=1; //计算f(n),结果用ans数组保存 for(int i=3;i<=20;i++){ ans[i]=(ans[i-1]+ans[i-2])*(i-1); } ans[1]=1; //重新赋值以免后面计算出现异常 cin>>t; while(t--){ cin>>a>>b; cout<<c(a,a-b)*ans[b]<<endl; } return 0; }