题目描述
某人写了n封信和n个信封,如果所有的信都装错了信封。求所有信都装错信封共有多少种不同情况。
输入输出格式
输入格式:一个信封数n(n<=20)
输出格式:一个整数,代表有多少种情况。
输入输出样例
输入样例#1:
2
输出样例#1:
1
输入样例#2:
3
输出样例#2:
2
裸数学题,推出递推公式就结束了,long long都不用,用搜索(或者手算)算出前三项就没了
推导过程:
原文链接
全错位排列:即被著名数学家欧拉(Leonhard Euler,1707-1783)称为组合数论的一个妙题的“装错信封问题”。 > 大意如下: 一个人写了n封不同的信及相应的n个不同的信封,他把这n封信都装错了信封,问都装错信封的装法有多少种? 分析: 假设有信封A,B,C,D...;信件1,2,3,4...;全部装错有f(n)种情况。 这里分两种情况考虑:①前面n-1个信封全部装错;②前面n-1个信封有一个没有装错其余全部装错。 ①前面n-1个信封全部装错:因为前面n-1个已经全部装错了,所以第n封只需要与前面任一一个位置交换即可,总共有f(n-1)*(n-1)种情况。 ②前面n-1个信封有一个没有装错其余全部装错:为什么考虑这种情况,因为n-1个信封中如果有一个没装错,那么我们把那个没装错的与n交换,即可得到一个全错位排列情况。 得到这种情况的种数也很简单,即是忽略掉那个没装错的情况去排列其他的信封的全错排种数f(n-2)*(n-1)。
#include <iostream>
using namespace std;
int dfs(int n)
{
if(n==0)
return 0;
if(n==1)
return 0;
if(n==2)
return 1;
return (n-1)*(dfs(n-1)+dfs(n-2));
}
int main()
{
int n;
cin>>n;
cout<<dfs(n);
return 0;
}