1. 程式人生 > 其它 >2021國慶CSP/NOIP衝刺營Contest02 B.排隊

2021國慶CSP/NOIP衝刺營Contest02 B.排隊

【題意】

n 名男生和 n 名女生要排成一列。女生用 0 表示,男生用 1 表示。當前佇列中已經站好了 m 位同學,現在剩下的 nm 個同學要補到隊列當中。這些同學可以站到佇列中的任意位置,但是佇列中原本的 m 個同學的相對位置不能發生改變。

此外,還有一個規定:對於每一個同學,他右邊男生的數量都不能小於女生的數量。

我們定義兩個方案是不同的,當且僅當存在一個位置,使得在兩個方案中這個位置上的同學性別不同。(也就是相同性別的同學不區分)

求所有人站好後有多少種列隊方案。答案對 998244353 取模。

【分析】

設f[i][j][k]表示現插入了i個,匹配到j對應的位置,剩餘k個女生在左側等待匹配的方案數

那麼直接轉移即可,注意一種填法可能對應多個匹配原串的方式,我們讓左括號儘可能地先匹配來避免算重

【程式碼】

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=998244353;
int n,m;
ll f[405][405][405];
int init[405];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++) scanf("%d",&init[i]);
    f[
0][0][0]=1; for(int i=0;i<=2*n-m;i++) for(int j=0;j<=m;j++) for(int k=0;k<=n;k++) { //填 0 能匹配儘量匹配 if(j<m && init[j+1]==0) f[i][j+1][k+1]=(f[i][j+1][k+1]+f[i][j][k])%mod; else f[i+1][j][k+1]=(f[i+1][j][k+1]+f[i][j][k])%mod;
// 填 1 能匹配儘量匹配 if(!k) continue; if(j<m && init[j+1]==1) f[i][j+1][k-1]=(f[i][j+1][k-1]+f[i][j][k])%mod; else f[i+1][j][k-1]=(f[i+1][j][k-1]+f[i][j][k])%mod; } printf("%d",f[2*n-m][m][0]); return 0; }