Description
定义F(0)为0,
F(1)为1,
F(i)为F(i-1)和F(i-2)拼起来。
给一个序列n,求F(x)所有序列n在每一个子序列出现的次数。
Sample Input
4 3 10
3 4 7 2
Sample Output
6
设f[x][l][r]为序列中l到r在F(x)中的价值。
可得转移当r == n时,那么
f
[
x
]
[
l
]
[
r
]
=
f
[
x
−
1
]
[
l
]
[
r
]
∗
2
l
e
n
[
F
(
x
−
2
)
]
f[x][l][r]=f[x-1][l][r]*2^{len[F(x-2)]}
f[x][l][r]=f[x−1][l][r]∗2len[F(x−2)]
否则
f
[
x
]
[
l
]
[
r
]
=
f
[
x
−
1
]
[
l
]
[
r
]
f[x][l][r]=f[x-1][l][r]
f[x][l][r]=f[x−1][l][r]
当l == 1时,
f
[
x
]
[
l
]
[
r
]
=
f
[
x
−
2
]
[
l
]
[
r
]
∗
2
l
e
n
[
F
(
x
−
1
)
]
f[x][l][r]=f[x-2][l][r]*2^{len[F(x-1)]}
f[x][l][r]=f[x−2][l][r]∗2len[F(x−1)]
否则
f
[
x
]
[
l
]
[
r
]
=
f
[
x
−
2
]
[
l
]
[
r
]
f[x][l][r]=f[x-2][l][r]
f[x][l][r]=f[x−2][l][r]
然后你就是左边一段分给F(x-1),右边一段分给F(x-2)即可。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const LL mod = 1e9 + 7;
int _min(int x, int y) {return x < y ? x : y;}
int _max(int x, int y) {return x > y ? x : y;}
int read() {
int s = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
return s * f;
}
LL f[110][110][110], bin[110];
char ss[110];
int main() {
int n = read(), x = read();
scanf("%s", ss + 1);
for(int i = 1; i <= n; i++) {
if(ss[i] == '0') f[0][i][i] = 1, f[1][i][i] = 0;
else f[0][i][i] = 0, f[1][i][i] = 1;
} bin[0] = bin[1] = 2; for(int i = 2; i <= x; i++) bin[i] = bin[i - 1] * bin[i - 2] % mod;
for(int k = 2; k <= x; k++) {
for(int len = 1; len <= n; len++) {
for(int l = 1; l <= n - len + 1; l++) {
int r = l + len - 1;
if(r == n) (f[k][l][r] += f[k - 1][l][r] * bin[k - 2] % mod) %= mod;
else (f[k][l][r] += f[k - 1][l][r]) %= mod;
if(l == 1) (f[k][l][r] += f[k - 2][l][r] * bin[k - 1] % mod) %= mod;
else (f[k][l][r] += f[k - 2][l][r]) %= mod;
for(int o = l; o < r; o++) {
(f[k][l][r] += f[k - 1][l][o] * f[k - 2][o + 1][r] % mod) %= mod;
}
}
}
} printf("%lld\n", f[x][1][n]);
return 0;
}