标签:一个 blank 初始化 ace 博客 思路 第一步 blog long
题意:n个数中m个数错排的情况个数
思路:先从n个新郎中选出m个,即 Cnm
再算出m个新郎的错排数,即 f(m)
错排:
当n个编号元素放在n个编号位置,元素编号与位置编号各不对应的方法数用f(n)表示,那么f(n-1)就表示n-1个编号元素放在n-1个编号位置,各不对应的方法数,其它类推.
第一步,把第n个元素放在一个位置,比如位置k,一共有n-1种方法
第二步,放编号为k的元素,这时有两种情况
( 1 ) 把它放到位置n,那么,对于剩下的n-1个元素,由于第k个元素放到了位置n,剩下n-2个元素就有f(n-2)种方法;
( 2 ) 第k个元素,不把它放到位置n,这时,对于这n-1个元素,有f(n-1)种方法;
综上得到:f (n) = (n-1)*( f(n-2) + f(n-1) )
特殊地,f(1)=0, f(2)=1
这里我将组合的求法由递归改为了递推
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 ll c[25][25],f[25]={0,0,1}; 5 void Init(){ 6 for(int n=0;n<=20;n++)//Cn 0和Cn n都置为1 7 c[n][0]=c[n][n]=1; 8 for(int n=1;n<=20;n++)//Cn 1到Cn n-1由递推公式求得 9 for(int m=1;m<n;m++) 10 c[n][m]=c[n-1][m-1]+c[n-1][m]; 11 for(int i=3;i<=20;i++)//规模为i的错排的递推 12 f[i]=(i-1)*(f[i-1]+f[i-2]); 13 } 14 int main(){ 15 Init();//初始化组合、错排表 16 ll t,n,m;cin>>t; 17 while(t--){ 18 cin>>n>>m; 19 cout<<c[n][m]*f[m]<<endl; 20 } 21 return 0; 22 }
参考博客:Hdu 2049解题报告
标签:一个 blank 初始化 ace 博客 思路 第一步 blog long
原文地址:https://www.cnblogs.com/Kanoon/p/12464649.html