洛谷 P1595:信封问题 ← 错排列

【题目来源】
https://www.luogu.com.cn/problem/P1595

【题目描述】
某人写了 n 封信和 n 个信封,如果所有的信都装错了信封。求所有信都装错信封共有多少种不同情况。

【输入格式】
一个信封数 n,保证 n≤20。

【输出格式】
一个整数,代表有多少种情况。​​​​​​​

【输入样例】
3

【输出样例】
2

【数据范围】
对于 100% 的数据,1≤n≤20。​​​​​​​

【算法分析】
● 错排(Derangement)问题是组合数学中的基本概念,指 n 个元素中的每个元素都不在其对应下标的位置上,即 ak≠k。其中,k∈[1,n]。
​​​​​​​例如:1 2 3 4的错排有: 4 3 2 1,4 1 2 3,4 3 1 2,3 4 1 2,3 4 2 1,2 4 1 3,2 1 4 3,3 1 4 2,2 3 4 1。

● 错排列公式:D(n)=(n-1)×(D(n-1)+D(n-2)),其中,D(1)=0,D(2)=1。
第一步,考虑第 n 个元素,把它放在某一个位置,比如位置 k,一共有 n-1 种放法;
第二步,考虑第 k 个元素,这时有两种情况:
(1)把它放到位置 n,那么对于除 n 以外的 n-1 个元素,由于第 k 个元素放到了位置 n,所以剩下 n-2 个元素的错排即可,有 D(n-2) 种放法;
(2)第 k 个元素不放到位置 n,这时对于这 n-1 个元素的错排,有 D(n-1) 种放法。 根据乘法和加法法则,综上可得:D(n)=(n-1)×(D(n-1)+D(n-2))。

● ​​​​​​​错排列公式:D(n)=nD(n-1)+(-1)^n,其中,D(1)=0。

【算法代码】

#include <bits/stdc++.h>
using namespace std;

long long d(int n) {
    if(n==1) return 0;
    if(n==2) return 1;
    return (n-1)*(d(n-1)+d(n-2));
}

int main() {
    int n;
    cin>>n;
    cout<<d(n);

    return 0;
}

/*
in:3
out:2
*/



【参考文献】
https://blog.csdn.net/hnjzsyjyj/article/details/156206151
https://www.luogu.com.cn/problem/solution/P1595
 

posted @ 2026-05-21 06:23  Triwa  阅读(28)  评论(0)    收藏  举报