题意:
有一个长度为n的01串要求任意两个1之间至少有k个0,求排队数,并对5000011取模。
题解:
设
f
[
i
]
f[i]
f[i]表示以1结尾,长度为i的排列种数。
因此,前一个1必须在0 ~
i
−
k
−
1
i - k - 1
i−k−1, (0表示i前面没有1)
所以
f
[
i
]
f[i]
f[i] =
∑
j
=
0
m
a
x
(
0
,
i
−
k
−
1
)
\sum_{j=0}^{max(0, i-k-1)}
∑j=0max(0,i−k−1)
f
[
j
]
f[j]
f[j]
特殊情况
f
[
0
]
f[0]
f[0] = 1
答案为
∑
i
=
0
n
\sum_{i=0}^{n}
∑i=0n
f
[
i
]
f[i]
f[i],
如果直接做,时间复杂度为O(
n
2
n^2
n2),会超时
因为每次求的都是一个前缀的和,所以可以在求出每个
f
[
i
]
f[i]
f[i]之后计算前缀和.时间复杂度为O(n).
s
[
i
]
s[i]
s[i] =
s
[
i
−
1
]
s[i - 1]
s[i−1] +
f
[
i
]
f[i]
f[i]
f
[
i
]
f[i]
f[i] =
s
[
m
a
x
(
0
,
i
−
k
−
1
)
]
s[max(0, i - k - 1)]
s[max(0,i−k−1)]
代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N = 100005;
const int MOD = 5000011;
int f[N], s[N];
int main(){
int i, n, k, j, t;
scanf("%d%d", &n, &k);
f[0] = 1;
s[0] = 1;
for(i = 1; i <= n; i++){
t = max(0, i - k - 1);
f[i] = s[t];
s[i] = (s[i - 1] + f[i]) % MOD;
}
printf("%d\n", s[n]);
return 0;
}