The 2nd Universal Cup. Stage 5: Northern J Sets May Be Good

题解#

我们考虑计算 S{1,2,3,,n}(1)cnt(S),这里 cnt(S) 表示 S 集合的导出子图的边数。

我们记 xi=[iS]

我们考虑删掉 n 号点。

注意到如果 xi 的取值会影响 cnt(s) 的奇偶性,则正负相消,贡献为 0

所以我们需要保证下列条件满足:

i=1n1an,ixi+an,n0(mod2)

我们考虑是否存在位置 pos,满足 an,pos(posn)=1

  1. 如果不存在这样的 pos,那我们根据 an,n 的取值分类讨论:

    1. an,n=0,则贡献乘 2
    2. an,n=1,贡献变成 0
  2. 如果存在一个位置 pos,满足 an,pos=1

    那么,根据 i=1n1an,ixi+an,n0(mod2),我们可以得出:

xposi=1iposn1an,ixi+an,n(mod2)

​ 我们考虑对于一个序列 x1,x2,,xn 计算答案。

i=1nj=i+1nai,jxixji=1n1j=i+1n1ai,jxixji=1iposn1j=i+1jposn1ai,jxixj+i=1iposn1ai,posxixpos+apos,posxposi=1iposn1j=i+1jposn1ai,jxixj+i=1iposn1ai,posxi(i=1iposn1an,ixi+an,n)+apos,pos(i=1iposn1an,ixi+an,n)

​ 于是,我们就可以把 n×n 的矩阵,在 O(n2w) 的时间内,变成 (n2)×(n2) 的矩阵。

​ 注意到 xn 有两种取值,所以贡献要 ×2。注意到上述式子继续展开,则 apos,posan,n 的项,所以贡献可能 ×(1)

总时间复杂度 O(n3w)

代码#

Copy
// MagicDark #include <bits/stdc++.h> #define debug cerr << "[" << __LINE__ << "] " #define SZ(x) (int) x.size() - 1 #define all(x) x.begin(), x.end() #define ms(x, y) memset(x, y, sizeof x) #define F(i, x, y) for (int i = (x); i <= (y); i++) #define DF(i, x, y) for (int i = (x); i >= (y); i--) using namespace std; typedef long long ll; typedef unsigned long long ull; template <typename T> inline void chkmax(T& x, T y) { x = max(x, y); } template <typename T> inline void chkmin(T& x, T y) { x = min(x, y); } template <typename T> inline void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48); x *= f; } const int N = 1010, MOD = 998244353, inv2 = (MOD + 1) >> 1; int n, m, ans = 1, t = 1; bitset <N> a[N]; signed main() { read(n), read(m); F(i, 1, n) t = 2 * t % MOD; F(i, 1, m) { int x, y; read(x), read(y); a[x][y] = a[y][x] = true; } DF(i, n, 1) { bool flag = false; F(j, 1, i - 1) flag |= a[i][j]; if (flag) { int pos = -1; F(j, 1, i - 1) if (a[j][i]) { pos = j; break; } assert(~pos); a[i][pos] = false; F(j, 1, i - 1) if (j != pos && a[pos][j]) { a[j] ^= a[i]; if (a[i][i] ^ a[i][j]) a[j][j].flip(); } F(j, 1, i - 1) if (j != pos && a[i][j]) { a[j] ^= a[pos]; } if (a[pos][pos]) { F(j, 1, i - 1) if (j != pos && a[i][j]) a[j][j].flip(); if (a[i][i]) ans = (ll) ans * (MOD - 1) % MOD; } F(j, 1, i - 2) { if (j >= pos) a[j] = a[j + 1]; bitset <N> s = (a[j] >> pos); a[j] = a[j] ^ (s << pos) ^ ((s >> 1) << pos); } i--; ans = (ll) ans * 2 % MOD; } else if (!a[i][i]) ans = (ll) ans * 2 % MOD; else ans = 0; } cout << (ll) (t + ans) * inv2 % MOD; return 0; } /* why? */
posted @   zhaohaikun  阅读(81)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示
CONTENTS