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 Kotlin (1.3.71) (judge verdict: Accepted)

import java.io.BufferedReader
import java.io.InputStreamReader
import kotlin.math.min

const val MOD = 998244353L

fun main() {
    val jin = BufferedReader(InputStreamReader(System.`in`))
    val line = jin.readLine().split(" ")
    val s = line[0]
    val k = line[1].toInt()
    val ones = mutableListOf<Int>()
    var curr = 0
    for (chara in s.reversed()) {
        when (chara) {
            '0' -> {
                ones.add(curr)
                curr = 0
            }
            '1' -> curr += 1
        }
    }
    ones.add(curr)
    var dp = Array(301) { LongArray(601) }
    dp[0][0] = 1L
    var j = 0
    for (nu in ones) {
        j++
        val dpUp = Array(301) { LongArray(601) }
        val dpDown = Array(301) { LongArray(601) }
        for (b in 0..300) {
            for (c in 0..600) {
                if (b > 0 && c > 0) {
                    dpUp[b][c] = dpUp[b - 1][c - 1]
                    dpUp[b][c] += dp[b - 1][c - 1]
                }
                if (b - nu - 1 >= 0 && c - nu - 1 >= 0) {
                    dpUp[b][c] -= dp[b - nu - 1][c - nu - 1]
                }
                dpUp[b][c] %= MOD
            }
        }
        for (b in 300 downTo 0) {
            for (c in 600 downTo 0) {
                if (b + 1 <= 300 && c > 0) {
                    dpDown[b][c] = dpDown[b + 1][c - 1]
                }
                dpDown[b][c] += dp[b][c]
                dpDown[b][c] %= MOD
            }
        }
        for (b in 0..300) {
            dp[b].fill(0L)
            for (c in 0..600) {
                dp[b][c] = dpDown[b][c] + dpUp[b][c]
                dp[b][c] %= MOD
            }
        }
    }
    var answer = 0L
    for (c in 0..min(600, 2 * k)) {
        answer += dp[0][c]
        answer %= MOD
    }
    answer += MOD
    answer %= MOD
    println(answer)
}