题解:AT_yahoo_procon2019_qual_e Odd Subrectangles
under_the_time · · 题解
题意
给定一个
n\times m 的\texttt{01} 矩阵A ,现在你要选出若干行与若干列,这些行与列会产生若干个交点,设这些交点的集合为S=\{(x_1,y_1),(x_2,y_2),\cdots,(x_k,y_k)\} ,求有多少种选法使得\sum_{i=1}^k A_{x_iy_i}\bmod2=1 即交点权值和为奇数,答案对998244353 取模。
题解
首先,权值和为奇数相当于权值异或和为
若找不到这样一个
这个问题等价于,给你
综上,答案为
代码
#include <bits/stdc++.h>
bool MemoryST; using namespace std;
#define ll long long
#define mk make_pair
#define open(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define abs(x) (((x) > (0)) ? (x) : (-(x)))
#define lowbit(x) ((x) & (-(x)))
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define BCNT __builtin_popcount
#define cost_time (1e3 * clock() / CLOCKS_PER_SEC) << "ms"
#define cost_space (abs(&MemoryST - &MemoryED) / 1024.0 / 1024.0) << "MB"
const int inf = 0x3f3f3f3f;
const ll linf = 1e18;
mt19937 rnd(random_device{}());
template<typename T> void chkmax(T& x, T y) { x = max(x, y); }
template<typename T> void chkmin(T& x, T y) { x = min(x, y); }
const int maxn = 2005, P = 998244353;
namespace ModOptions_normal {
int add(int x, int y) { return (x + y) % P; } void addto(int &x, int y) { (x += y) %= P; }
int mul(int x, int y) { return 1ll * x * y % P; } void multo(int &x, int y) { x = mul(x, y); }
int qp(int x, int y) {
int res = 1; for (; y; y >>= 1, multo(x, x))
if (y & 1) multo(res, x);
return res;
} int divv(int x, int y) { return 1ll * x * qp(y, P - 2) % P; } void divto(int &x, int y) { x = divv(x, y); }
int sub(int x, int y) { return (x + P - y) % P; } void subto(int &x, int y) { x = sub(x, y); }
} using namespace ModOptions_normal;
int n, m, a[maxn][maxn];
namespace LinearBasis {
bitset<maxn> b[maxn], cur;
int siz = 0;
void insert(int p) {
for (int i = 1; i <= m; i ++)
cur[i] = a[p][i];
for (int i = 1; i <= m; i ++) if (cur[i]) {
if (!b[i][i]) return siz ++, b[i] = cur, void(0);
cur ^= b[i];
}
}
} using namespace LinearBasis;
bool MemoryED; int main() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i ++) {
for (int j = 1; j <= m; j ++)
scanf("%d", &a[i][j]);
insert(i);
} printf("%d\n", mul(sub(qp(2, n), qp(2, n - siz)), qp(2, m - 1)));
return 0;
}