「1」で始まり、最大で「1」の数字が連続するバイナリシーケンスをほぼ有効と呼びましょう。m
i = 1, ..., nとは、正確に連続した「1」の数字で終わるj = 0, ..., m長さa(i, j)のほぼ有効なシーケンスの数です。ij
それで
a(1, 1) = 1およびa(1, j) = 0 for j != 1、長さ 1 のほぼ有効なシーケンスは「1」だけだからです。
- なぜなら
n >= 2、ほぼ有効な長さのシーケンスに「0」j = 0をa(i, 0) = a(i-1, 0) + a(i-1, 1) + ... + a(i-1, m)追加すると、「0」で終わるi-1ほぼ有効な長さのシーケンスが得られるからです。i
- なぜなら
n >= 2、後続のものj > 0を持つほぼ有効a(i, j) = a(i-1, j-1)なシーケンスに「1」を追加すると、後続のものを持つi-1ほぼ有効な長さのシーケンスが得られるからです。ji
最後に、必要な数はn、末尾に「1」がある、長さのあるほぼ有効なシーケンスの数であるため、これは
f(n, m) = a(n, 1) + a(n, 2) + ... + a(n, m)
C関数として書かれています:
int a[NMAX+1][MMAX+1];
int f(int n, int m)
{
int i, j, s;
// compute a(1, j):
for (j = 0; j <= m; j++)
a[1][j] = (j == 1);
for (i = 2; i <= n; i++) {
// compute a(i, 0):
s = 0;
for (j = 0; j <= m; j++)
s += a[i-1][j];
a[i][0] = s;
// compute a(i, j):
for (j = 1; j <= m; j++)
a[i][j] = a[i-1][j-1];
}
// final result:
s = 0;
for (j = 1; j <= m; j++)
s += a[n][j];
return s;
}
行列の最後の列のみaが必要なため、ストレージ要件はさらに改善される可能性があります。ランタイムの複雑さはO(n*m).