P2592 [ZJOI2008]生日聚會
阿新 • • 發佈:2020-07-22
容易發現已經結束掉的一個子串只要合法就對後面沒有影響,所以可以令 \(f_{i,j,p,q}\) 表示前 \(i+j\) 個人有 \(i\) 個男孩,\(j\) 個女孩,所有字尾中男孩最多比女孩多 \(p\) 個,女孩最多比男孩多 \(q\) 個的方案數。
轉移即列舉下一個位置是男孩或者女孩,記得對 \(0\) 取 \(\max\)。
時間複雜度 \(O(nmk^2)\)~
code:
#include<bits/stdc++.h> using namespace std; #define N 25 #define NN 155 #define Mod 12345678 #define Max(x,y)((x)>(y)?x:y) #define For(i,x,y)for(i=x;i<=(y);i++) int f[NN][NN][N][N]; int main() { int n,m,k,ans=0,i,j,p,q; cin>>n>>m>>k; f[0][0][0][0]=1; For(i,0,n) For(j,0,m) For(p,0,k) For(q,0,k) { if(p<k)f[i+1][j][p+1][Max(q-1,0)]=(f[i+1][j][p+1][Max(q-1,0)]+f[i][j][p][q])%Mod; if(q<k)f[i][j+1][Max(p-1,0)][q+1]=(f[i][j+1][Max(p-1,0)][q+1]+f[i][j][p][q])%Mod; } For(p,0,k) For(q,0,k)ans=(ans+f[n][m][p][q])%Mod; cout<<ans; return 0; }