Yahoo Programming Contest 2019 F - Pass
题目大意
给定一个只包含012序列,0表示这个人有2个红球,1表示一个红球一个蓝球,2表示两个蓝球。进行n*2次游戏,每次游戏所有有球的人选择一个球递给前一个人,第一个人把球放到一个序列中,'r'表示红球,'b'表示蓝球,问一共多少种序列
分析
一定要满足前i个人的所有红球>=序列前i个位置的红球,蓝球同理,然后dp
f[i][j]表示到第i个位置,有j个红球的方案数
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
const int mod = 998244353;
char s[100100];
int n,m,dp[4010][4010],sum[2010][2];
int main(){
int i,j,k;
scanf("%s",s+1);
n=strlen(s+1);
for(i=1;i<=n;i++){
if(s[i]=='0')sum[i][0]+=2;
else if(s[i]=='1')sum[i][0]++,sum[i][1]++;
else sum[i][1]+=2;
sum[i][0]+=sum[i-1][0],sum[i][1]+=sum[i-1][1];
}
if(sum[1][0])dp[1][0]=1;
if(sum[1][1])dp[1][1]=1;
for(i=2;i<=2*n;i++)
for(j=0;j<=i;j++){
if(j>sum[min(i,n)][1]||i-j>sum[min(i,n)][0])continue;
dp[i][j]=(dp[i][j]+dp[i-1][j])%mod;
if(j)dp[i][j]=(dp[i][j]+dp[i-1][j-1])%mod;
}
cout<<dp[2*n][sum[n][1]];
return 0;
}