其他分享
首页 > 其他分享> > 题解:LuoguP4921 情侣?给我烧了

题解:LuoguP4921 情侣?给我烧了

作者:互联网

题解:LuoguP4921 情侣?给我烧了

[MtOI2018]情侣?给我烧了! - 洛谷

题意简述

有 \(n\) 对情侣,\(2\) 列座位,座位共有 \(n\) 排。

求恰有 \(k\) 对情侣坐在了同一排座位上的方案数。

\(T\le 1000\) 组数据,每组数据给出一个整数 \(n\le 1000\) ,输出 \(k=0\sim n\) 时 的答案。

思路

设 \(G_K\) 表示恰好选择 \(k\) 对情侣坐在一排的方案数(\(k\) 对情侣已经确定)

\(F_k\) 表示选择 \(k\) 对情侣坐在一排的方案数(\(k\) 对情侣也已确定)

设任意 \(k\) 对情侣坐在一排的方案数(待求答案)为 \(ans_k\) 。

那么有 \(ans_k={n\choose k}^2\times k!\times 2^k\times D_{n-k}\)

座位选择*情侣选择*座位之间的排列*情侣二人之间互换位置*剩下n-k对情侣都不在座位上的"错排"

\(D_n\) 表示 \(2n\) 个座位,\(n\) 对情侣都不坐一起的方案数,显然 \(D_n\) = \(G_0\),

易知 \(F_k={n\choose k}^2\times k!\times 2^k\times (2(n-k))!\)

因为 \(F_k=\sum_{i=k}^{n}{{i\choose k}G(k)}\) ,(\(i\choose k\) 表示 \(i\) 对情侣选出确定的 \(k\) 对)。

观察到上式是二项式反演的标准形式之一,于是有:

\(G_k=\sum_{i=k}^{n}{(-1)^{i-k}}{i\choose k}F_i\)

解得: \(D_n=G_0=\sum_{i=0}^{n}{(-1)^{i}{n\choose i}^2}\times i!\times 2^i\times (2(n-i))!\) 。

带入原式 \(ans_k\) 即可。

最终解得:

\(ans_k={n\choose k}^2\times k!\times 2^k\times D_{n-k}\)

\(D_n=\sum_{i=0}^{n}{(-1)^{i}{n\choose i}^2}\times i!\times 2^i\times (2(n-i))!\)

#include <bits/stdc++.h>
const int N = 2050, mod = 998244353;
using LL = long long;
auto sign = [](int x)
    -> LL{ return (x & 1) ? -1 : 1; };
auto mul = [](LL a, LL b, LL c, LL d, LL e)
    -> LL{ return ((((a * b % mod) * c % mod) * d) % mod * e) % mod; };
LL inv[N], fac[N], D[N], pow2[N];
LL C(int x, int y) { return fac[x] * inv[y] % mod * inv[x - y] % mod; }
void init()
{
    fac[1] = inv[1] = fac[0] = inv[0] = pow2[0] = 1;
    pow2[1] = 2;
    for (int i = 2; i < N; i++)
        inv[i] = (mod - mod / i) * inv[mod % i] % mod,
        fac[i] = fac[i - 1] * i % mod,
        pow2[i] = (pow2[i - 1] << 1) % mod;
    for (int i = 2; i < N; i++)
        inv[i] = inv[i] * inv[i - 1] % mod;
    for (int n = 0; n < (N >> 1); n++)
        for (int i = 0; i <= n; i++)
            D[n] = (D[n] + sign(i) * mul(C(n, i), C(n, i), fac[i], pow2[i], fac[(n - i) << 1]) + mod) % mod;
}

int main()
{
    int T;
    scanf("%d", &T);
    init();
    while (T--)
    {
        int n;
        scanf("%d", &n);
        for (int i = 0; i <= n; i++)
            printf("%lld\n", mul(C(n, i), C(n, i), fac[i], pow2[i], D[n - i]));
    }
    return 0;
}

标签:LuoguP4921,题解,LL,情侣,times,choose,inv,mod
来源: https://www.cnblogs.com/mklzc/p/16504297.html