Solution -「FJWC 2020」人生

(mathcal{Description})

  OurOJ.

  有 (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;
}

原文地址:https://www.cnblogs.com/rainybunny/p/14567836.html