题解:qoj7303 City United

题意:给出一个图,问连通子图的个数模 \(2\),保证 \(n\le 50,(u,v)\) 满足 \(|u-v|\le 13\)

做法:

首先直接状压连通性,复杂度是贝尔数的,\(d=13\) 并通过不了。

考虑利用模 \(2\) 的性质,我定义一个集合 \(S\) 的权值为 \(2^{c(S)}\)\(c\) 是集合能分为多少个连通块,那么答案模 \(4\) 除以二就是模 \(2\) 的答案。

那么现在就等于我给这个图上黑白色,相连的点一定同色,也可以不涂色,问方案数。直接三进制状压即可,复杂度 \(O(3^{13}n)\)

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e6 + 5, mod = 4;
int n, m, e[55], pw[55];
int dp[2][maxn], msk[2][maxn];
int main() {
	cin >> n >> m;
	pw[0] = 1;
	for (int i = 1; i <= 13; i++)
		pw[i] = pw[i - 1] * 3;
	for (int i = 1; i <= m; i++) {
		int x, y; cin >> x >> y;
		if(x > y)
			swap(x, y);
		e[y] |= (1 << y - x - 1);
	}
	for (int i = 0; i < pw[13]; i++) {
		msk[0][i] = (msk[0][i / 3] << 1) | (i % 3 == 1);
		msk[1][i] = (msk[1][i / 3] << 1) | (i % 3 == 2);
	}
	dp[0][0] = 1;
	int cur = 0;
	for (int i = 1; i <= n; i++) {
		cur ^= 1;
		memset(dp[cur], 0, sizeof(dp[cur]));
		//cout << 123 << endl;
		for (int j = 0; j < pw[13]; j++) {
			dp[cur][j * 3 % pw[13]] = (dp[cur][j * 3 % pw[13]] + dp[cur ^ 1][j]) % mod;
			if((msk[1][j] & e[i]) == 0)
				dp[cur][(j * 3 + 1) % pw[13]] = (dp[cur][(j * 3 + 1) % pw[13]] + dp[cur ^ 1][j]) % mod;
			if((msk[0][j] & e[i]) == 0)
				dp[cur][(j * 3 + 2) % pw[13]] = (dp[cur][(j * 3 + 2) % pw[13]] + dp[cur ^ 1][j]) % mod;
		}
	}
	int res = 0;
	for (int i = 0; i < pw[13]; i++)
		res = res + dp[cur][i], res %= mod; 
	cout << ((res >> 1) & 1) << endl;
	return 0;
}
posted @ 2025-10-15 16:16  LUlululu1616  阅读(17)  评论(0)    收藏  举报