题目链接:
两道错排类递推问题 对错排有了深刻理解
这类题都是由信封问题演化来的:
n个信封对应n封信 问全部放错有几种方法
这类问题典型思路 以动归思想 化为小问题——
给第n封信找一个位置-K 有n-1种方法
给K找位置有两种
一是放在n的信封里(即n与K交换位置) 剩下的即为n-2封信的错排——dp[n-2]
二是放在其他位置 即n-1封信错排——dp[n-1]
总上n封信的错排有(n-1)(dp[n-2]+dp[n-1])种方案
以上便为n的错排
题目一:神、上帝以及老天爷
典型的错排类问题 唯一需要注意的是分母 为n的全排列
代码如下:
#include
#include
using namespace std;
int main()
{
int i;
long long int m[21];
long long int dp[21];
int n;
int c;
dp[1]=0;
dp[2]=1;
m[1]=1;
m[2]=2;
for(i=3;i<=20;i++)
{
dp[i]=(i-1)*(dp[i-1]+dp[i-2]);
m[i]=m[i-1]*i;
}
while(cin>>c)
{
while(c--)
{
cin>>n;
cout<
<
<
题目二:不容易系列之(4)——考新郎
与上题唯一的不同是限制了错排数目 而不是全错排 只需要用排列组合知识 算出在n个人中选出m个人来进行错排的方案数
代码如下:
#include
using namespace std;
int main()
{
ios::sync_with_stdio(false);
long long int dp[21];
long long int fm[21];
long long int x;
int i,n,m,c;
dp[1]=0;
dp[2]=1;
fm[1]=1;
fm[2]=2;
for(i=3;i<=20;i++)
{
dp[i]=(i-1)*(dp[i-1]+dp[i-2]);
fm[i]=fm[i-1]*i;
}
while(cin>>c)
{
while(c--)
{
cin>>n>>m;
x=1;
for(i=n;i>n-m;i--)
x*=i;
x/=fm[m];
cout<
<