设 fn,m 表示长度为 n 的序列(注意不是环),填了 m 个 1,没有长度 ≥c 的连续 1 子段的方案数。
考虑最后一位填了 0/1:
-
填 0:fn,m←fn−1,m
-
填 1:考虑要减去在 n 处恰好不满足的方案数,即序列为:⋯0111⋯1,最后 c 个 1,于是转移为:fn,m←fn−1,m−1−fi−c−1,j−c。注意 Corner Case:有可能第一个 0 对应的是序列的第 0 位置,此时应有:fc,c=0。
f[0][0]=1;
for(int i=1;i<=n;i++) for(int j=0;j<=i;j++)
{
f[i][j]=md(f[i-1][j]+(j?f[i-1][j-1]:0));
if(i==c){if(j==c) f[i][j]--;}
else if(i>c&&j>=c) f[i][j]=md(f[i][j]+mod-f[i-c-1][j-c]);
}