Luogu P4921 [MtOI2018]情侣?给我烧了!(错位排列)
- 易得: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;
}