https://www.lydsy.com/JudgeOnline/problem.php?id=2958
表示菜的不会去除重复的计算qwq
这里的状态\(f[i][j][pos]\)很强啊
主要是\(j\)是记录这位是多少
有效的防止重复计数
然后转移的时候手动的判断一下有多少转移到了下一状态
复杂度\(O(n)\)
dp这么菜怎么办..
#include <bits/stdc++.h>
#define int long long
#define fo(i, n) for(int i = 1; i <= (n); i ++)
#define out(x) cerr << #x << " = " << x << "\n"
#define type(x) __typeof((x).begin())
#define foreach(it, x) for(type(x) it = (x).begin(); it != (x).end(); ++ it)
using namespace std;
// by piano
template<typename tp> inline void read(tp &x) {
x = 0; char c = getchar(); bool f = 0;
for(; c < '0' || c > '9'; f |= (c == '-'), c = getchar());
for(; c >= '0' && c <= '9'; x = (x << 3) + (x << 1) + c - '0', c = getchar());
if(f) x = -x;
}
const int mo = 1e9 + 7;
const int N = 1e6 + 233;
int sumx[N], sumb[N], sumw[N], pw[N];
int n, K;
char str[N];
int f[3][2][N];
inline int doit(int pos, int fff) {
if(pos < K || str[pos - K] == (fff ? 'W' : 'B')) return 0;
int sum = (fff ? sumb[pos] - sumb[pos - K] : sumw[pos] - sumw[pos - K]);
if(sum) return 0;
else if(pos == K) return fff == 0 ? 1 : 0;
else return f[fff][fff ^ 1][pos - K];
}
main(void) {
read(n); read(K);
scanf("%s", str + 1);
pw[0] = 1;
for(int i = 1; i <= n; i ++) {
sumx[i] = sumx[i - 1] + (str[i] == 'X');
sumb[i] = sumb[i - 1] + (str[i] == 'B');
sumw[i] = sumw[i - 1] + (str[i] == 'W');
pw[i] = pw[i - 1] * 2 % mo;
}
f[0][0][0] = 1;
for(int i = 1; i <= n; i ++) {
if(str[i] != 'W') {
int tmp = doit(i, 0);
f[0][0][i] = (f[0][0][i - 1] + f[0][1][i - 1] - tmp) % mo;
f[1][0][i] = (f[1][0][i - 1] + f[1][1][i - 1] + tmp) % mo;
f[2][0][i] = (f[2][0][i - 1] + f[2][1][i - 1]) % mo;
}
if(str[i] != 'B') {
int tmp = doit(i, 1);
f[0][1][i] = (f[0][0][i - 1] + f[0][1][i - 1]) % mo;
f[1][1][i] = (f[1][0][i - 1] + f[1][1][i - 1] - tmp) % mo;
f[2][1][i] = (f[2][0][i - 1] + f[2][1][i - 1] + tmp) % mo;
}
}
int ans = (f[2][0][n] + f[2][1][n]) % mo;
ans = (ans + mo) % mo;
cout << ans << "\n";
}