首页 > 其他分享 >CF946F

CF946F

时间:2022-10-18 19:55:08浏览次数:42  
标签:matrix int CF946F len times 序列 mod

设 \(f_{i,j,k}\) 表示在串 \(F(i)\) 的子序列中,\(s\) 中区间 \([j,k]\) 作为子串的出现次数之和。

则有两种转移:一种是子序列完全包含在 \(F(i-1)\) 或 \(F(i-2)\) 中,一种是子序列跨越两端。

先讨论后一种情况:\(f_{i,j,k}=\sum\limits_{l=j}^{k-1}f_{i-1,j,l}\times f_{i-2,l+1,k}\)。

然后讨论前一种情况,先讨论子序列全部位于 \(F(i-1)\) 中的情况,发现当 \(k=n\) 时由于 \([j,n]\) 已经不可能继续扩展了,所以 \(F(i-2)\) 中的字符可以随便选。否则不能选,不然可能会算重。

这里说明一下为什么会算重:
如果选了的话,\([j,k]\) 一定能扩展为 \([j,k+1]\),这种情况属于子序列跨域两端,会在 \(f_{i,j,k+1}=f_{i-1,j,k}\times f_{i-2,k+1,k+1}\) 中被统计。

因此设 \(len_i\) 表示 \(F(i)\) 的长度,则有:

\(f_{i,j,k}=\left\{\begin{matrix} f_{i-1,j,k}\times 2^{len_i-2} \ \ \ \ k=n \\ f_{i-1,j,k} \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ k\ne n \end{matrix}\right.\)

子序列全部位于 \(F(i-2)\) 中的情况也同理:

\(f_{i,j,k}=\left\{\begin{matrix} f_{i-2,j,k}\times 2^{len_i-1} \ \ \ \ j=1 \\ f_{i-2,j,k} \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ j\ne 1 \end{matrix}\right.\)

初值为 \(f_{0,i,i}=[s_i=0],f_{1,i,i}=[s_i=1]\)。

最终答案为 \(f_{x,1,n}\)。

时间复杂度 \(\mathcal O(xn^3)\)。

Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 105, mod = 1e9 + 7;
int n, m;
char s[N];
int f[N][N][N];
int pw[N];

void add(int &a, int b) {
	a += b;
	if (a >= mod) a -= mod;
}

int main() {
	scanf("%d%d%s", &m, &n, s + 1);
	for (int i = 1; i <= m; ++i) f[s[i] - '0'][i][i] = 1;
	pw[0] = pw[1] = 2; for (int i = 2; i <= n; ++i) pw[i] = 1ll * pw[i - 1] * pw[i - 2] % mod;
	for (int i = 2; i <= n; ++i)
		for (int l = 1; l <= m; ++l)
			for (int r = l; r <= m; ++r) {
				add(f[i][l][r], 1ll * f[i - 1][l][r] * ((r == m) ? pw[i - 2] : 1) % mod);
				add(f[i][l][r], 1ll * f[i - 2][l][r] * ((l == 1) ? pw[i - 1] : 1) % mod);
				for (int k = l; k < r; ++k) add(f[i][l][r], 1ll * f[i - 1][l][k] * f[i - 2][k + 1][r] % mod);
			}
	printf("%d", f[n][1][m]);
	return 0;
}

标签:matrix,int,CF946F,len,times,序列,mod
From: https://www.cnblogs.com/Kobe303/p/16803867.html

相关文章