Yahoo Programming Contest 2019 F

传送门

题目大意

给定一个只包含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;
}
原文地址:https://www.cnblogs.com/yzxverygood/p/10527407.html