Luogu P4921 [MtOI2018]情侣?给我烧了!(错位排列)

image

  • 易得:ans = 选k对配对情侣得方案 Cn,k * 2^k * An,k * "错位排列" D[n-k]
  • 这个错排不是普通的错排(当时直接晕着脑袋套公式了),还有男男配对,女女配对的情况。
  • 剩下x队情侣进行"错排":
    思考一下,错排的条件不容易满足,需要进行模拟:
    第一个位置选出两个男的2x(x-1)
    ____ 他们的女友配对 : 两个女的位置交换* 可以放在x-1个位置上 * 剩余x-2对错排2(x-1)D[x-2]。
    ____ 他们的女友不配对 :剩余x-1对错排 D[x-1]。
    第一个位置选出两个女的,这种情况包含在上面的方案中
    第一个位置选出一男一女的,这种情况和上面方案相同

综上:D[i] = 4ll * i % mod * (i - 1) % mod * ( D[i - 1] + 2ll * (i - 1) * D[i - 2] % mod) % mod;

错排是排列过的
具体题目具体分析,不要盲目套公式
耐心模拟

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false) ,cin.tie(0), cout.tie(0);
//#pragma GCC optimize(3,"Ofast","inline")
#define ll long long
#define PII pair<int, char>
//#define int long long
const int N = 1e5 + 5;
const int M = 1e5 + 5;
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
const double PI = acos(-1.0);
ll F[N], inv[N], D[N];
ll C( ll n, ll m ) {
  return F[n] * inv[m] % mod * inv[n - m] % mod;
}
ll A ( ll n, ll m ) {
  return F[n] * inv[n - m] % mod;
}
ll qmi( ll m, ll k ) {
  ll res = 1 % mod;
  while( k ) {
      if( k & 1 ) res = res * m % mod;
      m = m * m % mod;
      k >>= 1;
  }
  return res;
}
void solve() {
  int n; cin >> n;
  for ( int k = 0; k <= n; ++ k ) {
      cout << C(n, k) * qmi( 2, k ) % mod * A(n, k) % mod * D[n - k] % mod << '\n';
  }
}

void init ( int n ) {
  F[0] = inv[0] = 1;
  for ( int i = 1; i <= n; ++ i ) F[i] = F[i - 1] * i % mod;
  inv[n] = qmi( F[n], mod - 2);
  for ( int i = n - 1; i >= 1; -- i ) inv[i] = inv[i + 1] * (i + 1) % mod;
  D[0] = 1, D[1] = 0;
  for ( int i = 2; i <= n; ++ i ) D[i] = 4ll * i % mod * (i - 1) % mod * ( D[i - 1] + 2ll * (i - 1) * D[i - 2] % mod) % mod;
}
int main() {
  IOS
  init( 1e5);
  int t; cin >> t;
  while( t -- ) solve();
  return 0;
}
posted @ 2022-07-08 10:34  qingyanng  阅读(18)  评论(0编辑  收藏  举报