题意:给出一个图,问连通子图的个数模 \(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;
}