Problem:
Score : 800 points

Problem Statement

Given is a string S consisting of 0 and 1. Find the number of strings, modulo 998244353, that can result from applying the following operation on S between 0 and K times (inclusive):

Choose a pair of integers i, j (1\leq i < j\leq |S|) such that the i-th and j-th characters of S are 0 and 1, respectively. Remove the j-th character from S and insert it to the immediate left of the i-th character.

Constraints

1 \leq |S| \leq 300

0 \leq K \leq 10^9

S consists of 0 and 1.

Input

Input is given from Standard Input in the following format:

S K

Output

Find the number of strings, modulo 998244353, that can result from applying the operation on S between 0 and K times (inclusive).

Sample Input 1

0101 1

Sample Output 1

4

Four strings, 0101, 0110, 1001, and 1010, can result.

Sample Input 2

01100110 2

Sample Output 2

14

Sample Input 3

1101010010101101110111100011011111011000111101110101010010101010101 20

Sample Output 3

113434815

Solution in C# (.NET Core 3.1.201) (judge verdict: Wrong Answer)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using static System.Math;
public static class P
{
    public static void Main()
    {
        _f(1000);
        for (int i = 0; i < Factorial.Count; i++)
            InvFactorial.Add(1 / Factorial[i]);

        var input = Console.ReadLine().Split();
        var s = input[0];
        var K = int.Parse(input[1]);
        //既に動かした文字についてはもう一度動かすことは考えなくて良い
        //前の奴が動くことで同型になる奴らってある?
        //押出をする場合はそれを除く 押し出しをする確率は、そこの奴らのどれかが動いている場合
        //どれも動いていない時に限って、その後に続く0に繋ぐことが許可される。
        //一様性でなんとかなるか?
        //それぞれが動く確率
        //余事象 Aが動き、Bが動き… 
        //「繋げられるブロックの数」も持っておく?動いたら-1ってことで 良さそう

        var size = Min(s.Length, K) + 1;

        //dp[動かした数(最小)][j個の場所に置ける]
        ModInt[][] dp = Enumerable.Repeat(0, size).Select(_ => new ModInt[s.Length + 3]).ToArray();
        dp[0][0] = 1;

        int cur1Streak = 0;

        void resolve()
        {
            ModInt[][] newdp = Enumerable.Repeat(0, size).Select(_ => new ModInt[s.Length + 3]).ToArray();
            //動かさない
            for (int i = 0; i < dp.Length; i++)
            {
                for (int j = 1; j < dp[i].Length; j++)
                {
                    newdp[i][j] = dp[i][j - 1];
                }
            }
            //動かす
            for (int nextMove = 1; nextMove <= cur1Streak; nextMove++)
            {
                for (int totalMove = nextMove; totalMove < dp.Length; totalMove++)
                {
                    //move個動かす→move個動かせるところが必要?そうでもない
                    for (int remainPlace = 1; remainPlace < dp[totalMove].Length; remainPlace++)
                    {
                        newdp[totalMove][remainPlace] += dp[totalMove - nextMove][remainPlace] * Combination(remainPlace - 1 + nextMove, nextMove);
                    }
                }
            }
            dp = newdp;
        }

        for (int i = 0; i < s.Length; i++)
        {
            if (s[i] == '1')
            {
                cur1Streak++;
                continue;
            }
            resolve();
            cur1Streak = 0;
        }
        resolve();

        Console.WriteLine(dp.Aggregate(new ModInt(0), (x, y) => y.Aggregate((x, y) => x + y) + x));
    }

    /// <summary>
    /// nCm
    /// </summary>
    static ModInt Combination(int n, int m) => Factorial[n] * InvFactorial[n - m] * InvFactorial[m];

    static List<ModInt> Factorial = new List<ModInt>() { 1 };
    static ModInt _f(int x)
    {
        for (int i = Factorial.Count; i <= x; i++) Factorial.Add(Factorial.Last() * i);
        return Factorial[x];
    }

    static List<ModInt> InvFactorial = new List<ModInt>();

    static ModInt Power(ModInt n, long m)
    {
        ModInt pow = n;
        ModInt res = 1;
        while (m > 0)
        {
            if ((m & 1) == 1) res *= pow;
            pow *= pow;
            m >>= 1;
        }
        return res;
    }
}


struct ModInt
{
    public const int Mod = 998244353;
    const long POSITIVIZER = ((long)Mod) << 31;
    long Data;
    public ModInt(long data) { if ((Data = data % Mod) < 0) Data += Mod; }
    public static implicit operator long(ModInt modInt) => modInt.Data;
    public static implicit operator ModInt(long val) => new ModInt(val);
    public static ModInt operator +(ModInt a, int b) => new ModInt() { Data = (a.Data + b + POSITIVIZER) % Mod };
    public static ModInt operator +(ModInt a, long b) => new ModInt(a.Data + b);
    public static ModInt operator +(ModInt a, ModInt b) { long res = a.Data + b.Data; return new ModInt() { Data = res >= Mod ? res - Mod : res }; }
    public static ModInt operator -(ModInt a, int b) => new ModInt() { Data = (a.Data - b + POSITIVIZER) % Mod };
    public static ModInt operator -(ModInt a, long b) => new ModInt(a.Data - b);
    public static ModInt operator -(ModInt a, ModInt b) { long res = a.Data - b.Data; return new ModInt() { Data = res < 0 ? res + Mod : res }; }
    public static ModInt operator *(ModInt a, int b) => new ModInt(a.Data * b);
    public static ModInt operator *(ModInt a, long b) => a * new ModInt(b);
    public static ModInt operator *(ModInt a, ModInt b) => new ModInt() { Data = a.Data * b.Data % Mod };
    public static ModInt operator /(ModInt a, ModInt b) => new ModInt() { Data = a.Data * GetInverse(b) % Mod };
    public static bool operator ==(ModInt a, ModInt b) => a.Data == b.Data;
    public static bool operator !=(ModInt a, ModInt b) => a.Data != b.Data;
    public override string ToString() => Data.ToString();
    public override bool Equals(object obj) => (ModInt)obj == this;
    public override int GetHashCode() => (int)Data;
    static long GetInverse(long a)
    {
        long div, p = Mod, x1 = 1, y1 = 0, x2 = 0, y2 = 1;
        while (true)
        {
            if (p == 1) return x2 + Mod; div = a / p; x1 -= x2 * div; y1 -= y2 * div; a %= p;
            if (a == 1) return x1 + Mod; div = p / a; x2 -= x1 * div; y2 -= y1 * div; p %= a;
        }
    }
}