洛谷P1595 信封问题 题解 二项式反演

题目链接:https://www.luogu.com.cn/problem/P1595

  • \(f_n\) 表示 恰好 装错 \(n\) 封信的方案数;
  • \(g_n\) 表示 装错 \(\le n\) 封信的方案数。

\[g_n = \sum_{i=0}^n f_i \]

根据 二项式反演 得

\[f_n = \sum_{i=0}^n \binom{n}{i} (-1)^{n-i} g_n \]

而本题中 \(g_n\) 就是 \(n\) 个数的全排列,即 \(g_n = n!\),所以

\[f_n = \sum_{i=0}^n \binom{n}{i} (-1)^{n-i} n! \]

示例程序:

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

long long fac[22] = {1}, flag[22] = {1}, c[22][22], ans;
int n;

void init(int n) {
    for (int i = 1; i <= n; i++)
        flag[i] = -flag[i-1], fac[i] = fac[i-1] * i;
    for (int i = 0; i <= n; i++) {
        for (int j = 0; j <= i; j++) {
            if (j == 0 || j == i)
                c[i][j] = 1;
            else
                c[i][j] = c[i-1][j-1] + c[i-1][j];
        }
    }
}

int main() {
    cin >> n;
    init(n);
    for (int i = 0; i <= n; i++)
        ans += c[n][i] * flag[n-i] * fac[i];
    cout << ans << endl;
    return 0;
}
posted @ 2026-04-06 14:51  quanjun  阅读(2)  评论(0)    收藏  举报