小强有一个长度为n的01字符串str,他想将字符串划分为几部分,且每部分都有且只有一个0,小强只会去验证划分方案的正确性,但是小强他不知道对于这个字符串一共有多少总划分的方案,请你告诉小强总的方案数,方案可能很大请对10^9十7取模。
要解决这个问题,核心是先判断字符串是否满足 “每部分有且只有一个 0” 的划分前提,若满足则计算相邻 0 之间 1 的数量组合,若不满足则方案数为 0。
一、核心判断:是否存在有效划分的前提
一个 01 字符串能被有效划分的唯一前提是:字符串中必须包含 0,且所有 0 的数量决定了划分的固定段数。
- 若字符串中没有 0:无法满足 “每部分有一个 0” 的要求,方案数直接为 0。
- 若字符串中有k 个 0:则必须划分为 k 段(每段 1 个 0),此时只需计算相邻 0 之间 1 的数量组合,即可得到总方案数。
二、方案数计算:相邻 0 之间的 1 决定组合数
当确定有 k 个 0 时,划分的关键在于 “如何在相邻 0 之间的 1 中插入分割线”,具体步骤如下:
- 提取相邻 0 的间隔:计算每两个连续 0 之间包含的 1 的数量,得到一个间隔列表。例如字符串 “010110”,0 的位置在 0、2、5,间隔 1 的数量为:第 1-2 个 0 之间有 1 个 1,第 2-3 个 0 之间有 2 个 1,间隔列表为 [1,2]。
- 计算每段间隔的可选数:对于两个 0 之间的 m 个 1,分割线只能插在 1 的 “缝隙” 中(包括前后),共有m + 1种选择。例如 m=1(1 个 1)时,有 2 种选择(在 1 前分割或 1 后分割);m=2(2 个 1)时,有 3 种选择。
- 总方案数为所有间隔可选数的乘积:将每个间隔的m + 1相乘,结果即为总方案数,最终对10^9 + 7取模。
三、示例验证
以具体例子说明计算过程,直观理解逻辑:
| 字符串 | 0 的数量 k | 相邻 0 的间隔(1 的数量) | 每间隔可选数(m+1) | 总方案数(乘积) | 结果(模 1e9+7) |
|---|---|---|---|---|---|
| "0" | 1 | 无间隔(k=1 时无分割) | 无 | 1 | 1 |
| "010" | 2 | [1] | 1+1=2 | 2 | 2 |
| "011010" | 3 | [2,1] | 2+1=3;1+1=2 | 3×2=6 | 6 |
| "111" | 0 | 无 | 无 | 0 | 0 |
四、算法步骤(可直接落地代码)
- 遍历字符串,统计 0 的个数zero_count,并记录每个 0 的位置。
- 若zero_count == 0,返回 0;若zero_count == 1,返回 1。
- 计算相邻 0 的位置差,减去 1(得到间隔的 1 的数量 m),生成间隔列表。
- 初始化结果res = 1,遍历间隔列表,将每个(m + 1)与res相乘,每次相乘后对10^9 + 7取模。
- 返回最终的res。
算法实现
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void (async function () {
// Write your code here
let params = [];
while ((line = await readline())) {
let tokens = line.split(" ");
params.push(tokens);
}
// console.log(params)
let MOD = 1e9 + 7;
let n = parseInt(params[0][0]);
let str = params[1][0];
function count(str) {
let zeroPositions = [];
for (let i = 0; i < str.length; i++) {
if (str[i] === "0") {
zeroPositions.push(i);
}
}
let zeroCount = zeroPositions.length;
if (zeroCount === 0) {
// console.log(0);
return 0;
}
if (zeroCount === 1) {
// console.log(1);
return 1;
}
let ans = 1;
for (let i = 1; i < zeroCount; i++) {
ans = (ans * (zeroPositions[i] - zeroPositions[i - 1])) % MOD;
}
return ans;
}
console.log(count(str));
})();