题解: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;
}

浙公网安备 33010602011771号