dp + 计数,CF 1920 E - Counting Binary Strings
目录
一、题目
1、题目描述
2、输入输出
2.1输入
2.2输出
3、原题链接
二、解题报告
1、思路分析
2、复杂度
3、代码详解
一、题目
1、题目描述
2、输入输出
2.1输入
2.2输出
3、原题链接
E - Counting Binary Strings |
二、解题报告
1、思路分析
对于一个01串,我们怎么计算其好子串的数目呢?
000 1 0000 1 00 1 00000
3 4 2 5
数目 = 4 * 5 + 5 * 3 + 3 * 6
可见,我们只关注 连续0 的组数
考虑dp,为了转移我们显然要知道最后一段的0的长度
定义 f(sum, cur) 为 好子串个数为sum,最后一段0的长度为cur,的字符串的数目
我们枚举cur 前一个 0串的长度,pre
那么 f(sum, cur) = Σ f(sum - (cur + 1) * (pre + 1), pre)
最终输出 sum(f(n)) 即可
2、复杂度
时间复杂度: O(nklogn)空间复杂度:O(nk)
3、代码详解
#include <bits/stdc++.h>
// #include <ranges>
using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;
constexpr int P = 998244353;
constexpr int inf32 = 1E9 + 7;
void solve() {
int n, k;
std::cin >> n >> k;
std::vector<std::vector<int>> f(n + 1, std::vector<int>(k + 1));
int res = 0;
f[0].assign(n + 1, 1);
for (int sum = 1; sum <= n; ++ sum) {
for (int cur = 0; cur < k; ++ cur) {
for (int pre = 0; (cur + 1) * (pre + 1) <= sum and cur + pre < k; ++ pre) {
f[sum][cur] += f[sum - (pre + 1) * (cur + 1)][pre];
if (f[sum][cur] >= P) f[sum][cur] -= P;
}
}
}
for (int x : f[n]) {
res += x;
if (res >= P) res -= P;
}
std::cout << res << '\n';
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int t = 1;
std::cin >> t;
while (t--) {
solve();
}
return 0;
}