错排问题【DP】

>Link

ybtoj错排问题


>解题思路

f n f_n fn为长度为 n n n的序列的合法排列数
对于第 n n n个数,按照题意可以放在前面 n − 1 n-1 n1中任意一个位置,设数 n n n准备放在第 k k k个位置
我们可以先排出 n − 1 n-1 n1个数的合法情况,再把第 k k k个数与第 n n n个数交换(不能是插入,插入会影响后面的数的坐标,但是怎样交换都不会使序列不合法)
此时有两个情况:

  1. 原本的第 k k k个数放在第 n n n位,剩下的数的合法排列为 f n − 2 f_{n-2} fn2
  2. 原本的第 k k k个数放在第 n n n位,剩下的数的合法排列为 f n − 1 f_{n-1} fn1

因此 f n = ( n − 1 ) ∗ ( f n − 1 + f n − 2 ) f_n=(n-1)*(f_{n-1}+f_{n-2}) fn=(n1)(fn1+fn2)


>代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
using namespace std;

int n;
LL f[25];

int main()
{
    
    
	scanf ("%d", &n);
	f[2] = 1;
	for (int i = 3; i <= n; i++)
	  f[i] = (i - 1) * (f[i - 1] + f[i - 2]);
	printf ("%lld", f[n]); 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43010386/article/details/111708647
今日推荐