给你 3 个正整数 zero
,one
和 limit
。
一个
二进制数组
arr
如果满足以下条件,那么我们称它是 稳定的 :
- 0 在
arr
中出现次数 恰好 为zero
。 - 1 在
arr
中出现次数 恰好 为one
。 arr
中每个长度超过limit
的子数组
都 同时 包含 0 和 1 。
请你返回 稳定 二进制数组的 总 数目。
由于答案可能很大,将它对 109 + 7
取余 后返回。
示例 1:
输入:zero = 1, one = 1, limit = 2
输出:2
解释:
两个稳定的二进制数组为 [1,0]
和 [0,1]
,两个数组都有一个 0 和一个 1 ,且没有子数组长度大于 2 。
示例 2:
输入:zero = 1, one = 2, limit = 1
输出:1
解释:
唯一稳定的二进制数组是 [1,0,1]
。
二进制数组 [1,1,0]
和 [0,1,1]
都有长度为 2 且元素全都相同的子数组,所以它们不稳定。
示例 3:
输入:zero = 3, one = 3, limit = 2
输出:14
解释:
所有稳定的二进制数组包括 [0,0,1,0,1,1]
,[0,0,1,1,0,1]
,[0,1,0,0,1,1]
,[0,1,0,1,0,1]
,[0,1,0,1,1,0]
,[0,1,1,0,0,1]
,[0,1,1,0,1,0]
,[1,0,0,1,0,1]
,[1,0,0,1,1,0]
,[1,0,1,0,0,1]
,[1,0,1,0,1,0]
,[1,0,1,1,0,0]
,[1,1,0,0,1,0]
和 [1,1,0,1,0,0]
。
提示:
1 <= zero, one, limit <= 1000
class Solution {
public:
// 问题?
// 剩余 i 个 0 ,j 个 1 , 如何组合出符合条件的二进制数组
// 递归 dfs(i,j)
// 这个dfs返回的是 这些符合条件的二进制数组个数
// 但是如此传参无法有效的判断
// 现在思考,如何解决
/*
* 这里对于每一个位置dfs(i,j),仅仅只有两种选择,选与不选
* 所以说每一次都是在填一个 0 | 1
* 填了之后 下一次 就是dfs(i-1,j) | dfs(i,j-1)
* 这dfs(i-1,j),dfs(i,j-1)有什么关系,画出递归树可以发现,是两个子树
* 那么dfs(i,j) = dfs(i-1,j) + dfs(i,j-1)
* 这样就出现问题了,因为有限制
* 不可能是dfs(i-1,j) | dfs(i,j-1)拼接起来的都符合
* 所以说得删除
* 那一些需要删除的呢?
* 假如本次是dfs(i,j)本次我填写一个0 ,limit = 2;
* 那么意思是dfs(i-1-limit,j)这个地方还填 0,就不符合了,需要删除这个
* 也就是dfs(i,j) = dfs(i-1,j) + dfs(i,j-1) + dfs(i-1-limit,j);
* 所以说我们应该多填一个参数在dfs中
* 这个参数来表示这次要填写什么
* 也就是变成了dfs(i,j,0) + dfs(i,j,1) = 原来的 dfs(i,j) 这样
* 那么对于任意的dfs(i,j,0) = dfs(i-1,j,0) + dfs(i-1,j,1) - dfs(i-limit-1,j,1);
* 这里为什么是-dfs(i-limit-1,j,1),因为这样的仅仅只存在dfs(i-limit-1,j,1)
* 不可能存在dfs(i-limit-1,j,0)因为这个是不合法的
* 并且dfs(i-limit-1,j,0) + dfs(i-limit-1,j,1) = dfs(i-limit-1,j)
*/
const int MOD = 1e9 + 7;
int numberOfStableArrays(int zero, int one, int limit) {
vector<vector<array<int, 2>>> memo(zero + 1, vector<array<int, 2>>(one + 1, {-1, -1}));
function<int(int, int, int)> dfs = [&](int i, int j, int k)-> int {
if (i == 0) {
return k == 1 && j <= limit;
}
if (j == 0) {
return k == 0 && i <= limit;
}
if (memo[i][j][k] != -1) {
return memo[i][j][k];
}
if (k == 0) {
return memo[i][j][k] = ((long long)dfs(i - 1, j, 0) + dfs(i - 1, j, 1) + (i > limit
? MOD - dfs(i - 1 - limit, j, 1)
: 0)) % MOD;
}
else {
return memo[i][j][k] = ((long long)dfs(i, j - 1, 0) + dfs(i, j - 1, 1) + (j > limit
? MOD - dfs(i, j - 1 - limit, 0)
: 0)) % MOD;
}
};
return (dfs(zero,one,0) + dfs(zero,one,1))%MOD;
}
};