(mathcal{Description})
有 (n) 个结点,一些结点有染有黑色或白色,其余待染色。将 (n) 个结点染上颜色并连接有向边,求有多少个不同(结点颜色不同或边不同)的图,满足:
- (forall lang u,v angin E,~1le u<vle n);
- 相邻两点颜色不同的路径条数(包括单点)为奇数。
答案对 (998244353) 取模。
(nle2 imes10^5)。
(mathcal{Solution})
DP,显然从后往前考虑每个结点的连边情况。为方便理解,不妨设 (g(u)) 表示在某个确定的图上,从 (u) 出发的合法路径条数。发现对 (g(u)) 的奇偶性有影响的连边 (lang u,v ang) 中,应满足 (v) 与 (u) 异色且 (2 otmid g(v)),且我们只关心如此 (v) 的个数。
然则需求信息量较小,可以开始 DP,令 (f(i,w,b)) 表示已为大于等于 (i) 的结点染好颜色,且白色的满足 (2 otmid g(v)) 的 (v) 有 (w) 个,黑色的满足 (2 otmid g(v)) 的 (v) 有 (b) 个。对于 (f(i+1,w,b)),一共已经确定完 (c=n-i+1) 个结点,不妨设 (i) 的颜色为白色,则有转移:
- (f(i,w,b)longleftarrow [b ot=0]2^{c-1}f(i+1,w,b));
- (f(i,w+1,b)longleftarrow2^{c-[b ot=0]}f(i+1,w,b));
答案则为
[sum_{2mid(w+b)}f(1,w,b)
]
注意到转移仅与 (w,b) 是否为 (0) 有关,答案仅与 (w,b) 的奇偶性有关,所以可以优化 (f(i,win[0,2],bin[0,2])) 为:已为大于等于 (i) 的结点染好颜色,且白色的满足 (2 otmid g(v)) 的 (v) 未出现 / 出现奇数次 / 出现偶数次,黑色同理,就能转移啦。
复杂度 (mathcal O(n)),带约 (10) 倍常数。
(mathcal{Code})
/* Clearink */
#include <cstdio>
#define rep( i, l, r ) for ( int i = l, repEnd##i = r; i <= repEnd##i; ++i )
#define per( i, r, l ) for ( int i = r, repEnd##i = l; i >= repEnd##i; --i )
const int MAXN = 2e5, MOD = 998244353;
int n, a[MAXN + 5], pwr[MAXN + 5], f[MAXN + 5][3][3];
// 0: none, 1: odd, 2: even.
inline int mul( const long long a, const int b ) { return a * b % MOD; }
inline int add( int a, const int b ) { return ( a += b ) < MOD ? a : a - MOD; }
inline void addeq( int& a, const int b ) { ( a += b ) >= MOD && ( a -= MOD ); }
int main() {
freopen( "life.in", "r", stdin );
freopen( "life.out", "w", stdout );
scanf( "%d", &n ), pwr[0] = 1;
rep ( i, 1, n ) {
scanf( "%d", &a[i] );
pwr[i] = add( pwr[i - 1], pwr[i - 1] );
}
f[n + 1][0][0] = 1;
per ( i, n + 2, 2 ) {
int all = n - i + 1, cur;
rep ( w, 0, 2 ) rep ( b, 0, 2 ) {
if ( !( cur = f[i][w][b] ) ) continue;
if ( !a[i - 1] ) {
addeq( f[i - 1][w][b], mul( cur, b ? pwr[all - 1] : 0 ) );
addeq( f[i - 1][( w & 1 ) + 1][b], mul( cur, pwr[all - !!b] ));
} else if ( ~a[i - 1] ) {
addeq( f[i - 1][w][b], mul( cur, w ? pwr[all - 1] : 0 ) );
addeq( f[i - 1][w][( b & 1 ) + 1], mul( cur, pwr[all - !!w] ));
} else {
addeq( f[i - 1][w][b], mul( cur, b ? pwr[all - 1] : 0 ) );
addeq( f[i - 1][w][b], mul( cur, w ? pwr[all - 1] : 0 ) );
addeq( f[i - 1][( w & 1 ) + 1][b], mul( cur, pwr[all - !!b] ));
addeq( f[i - 1][w][( b & 1 ) + 1], mul( cur, pwr[all - !!w] ));
}
}
}
int ans = 0;
rep ( w, 0, 2 ) rep ( b, 0, 2 ) {
if ( ( w + b ) & 1 ) {
addeq( ans, f[1][w][b] );
}
}
printf( "%d
", ans );
return 0;
}