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 (GCC 9.2.1) (judge verdict: Accepted)

#include <stdio.h>

#define Mod 998244353

long long div_mod(long long x, long long y, long long z)
{
	if (x % y == 0) return x / y;
	else return (div_mod((1 + x / y) * y - x, (z % y), y) * z + x) / y;
}

long long combination(int n, int k)
{
	if (k == 0) return 1;
	
	static long long ans[300][300] = {};
	if (ans[n][k] != 0) return ans[n][k];
	
	int i;
	long long x, y;
	for (i = n, x = 1; i >= n - k + 1; i--) x = x * i % Mod;
	for (i = 2, y = 1; i <= k; i++) y = y * i % Mod;
	ans[n][k] = div_mod(x, y, Mod);
	return ans[n][k];
}

int main()
{
	int K;
	char S[301];
	scanf("%s %d", S, &K);

	int i, j, k, l, m, count[151][2] = {}, sum[2] = {};
	count[0][S[0] - '0']++;
	for (l = 1, k = 0; S[l] != 0; l++) {
		if (S[l] == S[l-1] || S[l] == '1') count[k][S[l] - '0']++;
		else count[++k][0]++;			
	}
	
	long long dp[151][301][301] = {};
	if (count[0][0] == 0) i = 1;
	else i = 0;
	dp[i][0][count[i][0]+1] = 1;
	for (j = 1; j <= count[i][1]; j++) {
		for (k = 1; k <= count[i][0]; k++) dp[i][j][k] = combination(j + count[i][0] - k - 1, j - 1);
	}
	
	for (sum[0] = count[i][0], sum[1] = count[i++][1]; count[i][1] > 0; i++) {
		for (l = 0; l <= sum[1]; l++) {
			for (k = 1; k <= sum[0] + 1; k++) dp[i][l][k+count[i][0]] = dp[i-1][l][k];
		}
		sum[0] += count[i][0];
		for (j = 1; j <= count[i][1]; j++) {
			for (l = 0; l <= sum[1]; l++) {
				for (k = 1; k <= sum[0]; k++) {
					for (m = sum[0] - count[i][0] + 1; m >= k - count[i][0] + 1 && m >= 1; m--) dp[i][l+j][k] = (dp[i][l+j][k] + dp[i-1][l][m] * combination(j + m + count[i][0] - k - 2, j - 1)) % Mod;
				}
			}
		}
		sum[1] += count[i][1];
	}
	
	long long ans = 0;
	for (j = 0; j <= K && j <= sum[1]; j++) {
		for (k = 1; k <= sum[0] + 1; k++) ans = (ans + dp[i-1][j][k]) % Mod;
	}
	printf("%lld\n", ans);
	fflush(stdout);
	return 0;
}