读题把子序列读成子串, 码都码完了, 样例不对, 人傻了。
我dp的是每个匹配串的贡献, 然后发现子序列的话算贡献维护不了。。
没想到直接dp的就是在子序列中出现的次数。
dp[ i ][ l ][ r ] 表示的是在 F[ i ]这个串中, s[ l ] - s[ r ]这个子串在所有子序列中的出现次数。
#include<bits/stdc++.h> #define LL long long #define LD long double #define ull unsigned long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ALL(x) (x).begin(), (x).end() #define fio ios::sync_with_stdio(false); cin.tie(0); using namespace std; const int N = 100 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const double eps = 1e-8; const double PI = acos(-1); template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;} template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;} template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;} template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;} LL power(LL a, LL b) { LL ans = 1; while(b) { if(b & 1) ans = ans * a % mod; a = a * a % mod; b >>= 1; } return ans; } int n, x; char s[N]; LL fib[N]; LL f[N][N][N]; LL dp(int x, int l, int r) { LL& ans = f[x][l][r]; if(~ans) return ans; ans = 0; if(x == 0) { if(l == r && s[l] == '0') ans = 1; } else if(x == 1) { if(l == r && s[l] == '1') ans = 1; } else { if(r == n) add(ans, dp(x - 1, l, r) * power(2, fib[x - 2]) % mod); else add(ans, dp(x - 1, l, r)); if(l == 1) add(ans, dp(x - 2, l, r) * power(2, fib[x - 1]) % mod); else add(ans, dp(x - 2, l, r)); for(int k = l; k < r; k++) add(ans, dp(x - 1, l, k) * dp(x - 2, k + 1, r) % mod); } return ans; } int main() { memset(f, -1, sizeof(f)); fib[0] = fib[1] = 1; for(int i = 2; i <= 100; i++) fib[i] = (fib[i - 1] + fib[i - 2]) % (mod - 1); scanf("%d%d", &n, &x); scanf("%s", s + 1); printf("%lld", dp(x, 1, n)); return 0; } /* */