2021國慶CSP/NOIP衝刺營Contest02 B.排隊
阿新 • • 發佈:2021-10-31
【題意】
有 n 名男生和 n 名女生要排成一列。女生用 0 表示,男生用 1 表示。當前佇列中已經站好了 m 位同學,現在剩下的 n−m 個同學要補到隊列當中。這些同學可以站到佇列中的任意位置,但是佇列中原本的 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; }