BZOJ3269 序列染色

BZOJ3269 序列染色

做完这题觉得很有意思,结果发现网上都不是我这么做的,那就是我很有意思 😁?

设两个二维 dp \(f[i][j],g[i][j]\) 分别表示目前到了第 i 位,B 匹配到了第 j 个的方案数和 B 已经匹配完成,W 匹配到了第 j 个的方案数。我这里是用所有的方案减去不合法的方案数即 \(2^{cnt}-\sum_{i=0}^{k-1}f_i+g_i\) 注:\(f_k\) 自动挪到 \(g_0\) 上。

考虑如何转移,如果新加入进来一个 B,那么 g 数组归零,f 数组整体右移一位即可,归零指所有的数加到 \(g_0\) 上然后清零即可。新加入 W 同理,加入 X 也是同理。这样我们发现无非是两个操作,把序列的和加到 0 位置上和整体右移,因此我们维护一个指针左移来实现整体右移,同时维护所有的和即可。看起来确实要比网上简洁一些。

/*
     />  フ
     |  _  _|
     /`ミ _x 彡
     /      |
    /   ヽ   ?
 / ̄|   | | |
 | ( ̄ヽ__ヽ_)_)
 \二つ
 */

#include <queue>
#include <vector>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MP make_pair
#define ll long long
#define fi first
#define se second
using namespace std;

template <typename T>
void read(T &x) {
    x = 0; bool f = 0;
    char c = getchar();
    for (;!isdigit(c);c=getchar()) if (c=='-') f=1;
    for (;isdigit(c);c=getchar()) x=x*10+(c^48);
    if (f) x=-x;
}

template<typename F>
inline void write(F x, char ed = '\n') {
	static short st[30];short tp=0;
	if(x<0) putchar('-'),x=-x;
	do st[++tp]=x%10,x/=10; while(x);
	while(tp) putchar('0'|st[tp--]);
	putchar(ed);
}

template <typename T>
inline void Mx(T &x, T y) { x < y && (x = y); }

template <typename T>
inline void Mn(T &x, T y) { x > y && (x = y); }

const int P = 1e9 + 7;
ll fpw(ll x, ll mi) {
	ll res = 1;
	for (; mi; mi >>= 1, x = x * x % P)
		if (mi & 1) res = res * x % P;
	return res;
}

void add(ll &x, ll y) { 
	x += y, x >= P && (x -= P);
}

const int N = 4000500;
ll F[N], G[N], *f = F + 2000000, *g = G + 2000000, cnt, n, k;
char s[N];
ll sumf, sumg, clf, clg;
int main() {
//	freopen ("color.in","r",stdin);
//	freopen ("color.out","w",stdout);
	read(n), read(k);
	scanf ("%s", s + 1);
	clf = clg = k + 1;
	sumf = f[0] = 1;
	for (int i = 1;i <= n; i++) {
		if (s[i] == 'B') {
			clg = 1; g[0] = sumg;
			if (clf >= k) {
				add(g[0], f[k-1]), add(sumg, f[k-1]);
				add(sumf, P - f[k-1]);
			}
			clf++, f--;
		}
		else if (s[i] == 'W') {
			clf = 1, f[0] = sumf;
			if (clg >= k) add(sumg, P - g[k-1]);
			g--, clg++;
		}
		else if (s[i] == 'X') {
			cnt++; 
			ll s1 = sumf, s2 = sumg;
			ll t = clf >= k ? f[k-1] : 0, tg = clg >= k ? g[k-1] : 0;
			f--, g--, clf++, clg++;
			add(sumf, sumf), add(sumg, sumg), add(sumf, P - t), add(sumg, P - tg);
			f[0] = s1, g[0] = s2, add(g[0], t), add(sumg, t);
		}
	}
	ll ans = fpw(2, cnt);
	for (int i = 0;i < k; i++) {
		if (clf > i) add(ans, P - f[i]);
		if (clg > i) add(ans, P - g[i]);
	}
	write(ans);
	return 0;
}
posted @ 2020-08-29 14:41  Hs-black  阅读(152)  评论(0编辑  收藏  举报