---
# System prepended metadata

title: 'Pusheen Contest 2023 #2'
tags: [CLA K22]

---

# Pusheen Contest 2023 #2
###### tags: `CLA K22`

## TEAMBUILDING
Chia một dãy nhị phân thành các nhóm gồm các kí tự liên tiếp sao cho mỗi kí tự thuộc 1 nhóm mỗi nhóm có chênh lệch kí tự `0` và `1` không quá $k$.

### Subtask 1: $1 \leq n \leq 20$

Quay lui

```c++
int count = 0;
void backtrack(int i) {
    if (i > n) {
        ++count;
        return;
    }
    int diff = 0;
    for(int j = i; j <= n; ++j) {
        diff += (s[j] == '0') ? -1 : 1;
        if (abs(diff) <= k) backtrack(j+1);
    }
}
```

### Subtask 3: $1 \leq n \leq 5000$

Quy hoạch động

Công thức truy hồi 
$$
\begin{cases}
dp[1] = 1 \\
dp[i] = \sum_j dp[j-1] && \text{ nếu } j \leq i \text{ và abs(diff}(i, j)) \leq k 
\end{cases}
$$
```c++
#include <bits/stdc++.h>
using namespace std;

int n, k;
string s;
const int N = 5005;
const int MOD = 1e9+7;
int dp[N];

void Input() {
	cin >> n >> k;
	cin >> s;
}

void add(int &a, int b) {
	a += b; if (a >= MOD) a -= MOD;
}

void Solve() {
	s = '#' + s;
	dp[0] = 1;
	for(int i = 1; i <= n; ++i)+ {
		int diff = 0;
		for(int j = i-1; j >= 0; --j) {
			diff += s[j+1] == '0' ? -1 : 1;
			if (abs(diff) <= k) add(dp[i], dp[j]);
		}
	}
	cout << dp[n];
}

int main(){
	ios::sync_with_stdio(0); cin.tie(0);
	Input(), Solve();
	return 0;
}

```
