题解:AT_yahoo_procon2019_qual_e Odd Subrectangles

怎么题解全是线性基,来点高消做法。

Solution

性质:对矩阵进行初等变换(模 \(2\) 意义下),答案不变。

  • 交换不用说。
  • 一行加上另一行相当于异或两行。记 \(x,y\) 是原来两行的 \(1\) 个数,\(y'\) 是两行异或后的 \(1\) 个数,容易发现 \(y'\equiv x+y\pmod 2\),证明就是异或只会减少成对的 \(1\)。那么原来选了两行,就把第一行删掉;只选了第二行,就加入第一行。方案一一对应,答案不变。
  • 一列加上另一列同理。

我们直接用高消消成对角线,记消完剩下 \(r\)\(1\),答案就是:

\[2^{n+m-2r}\sum_{i=1}^{r}[i\bmod2=1]\binom{r}{i}3^{r-i} \]

左边的 \(2^{n+m-2r}\) 是为 \(0\) 的行列,随便选;右边枚举选中的 \(1\) 的个数 \(i\),从 \(r\) 个中选出 \(1\) 个,剩下 \(r-i\)\(1\) 只有不是行列同时选就行了,方案为 \(3^{r-i}\)

用 bitset 优化,时间复杂度 \(\mathcal{O}(\dfrac{n^2m}{\omega})\)

Code

namespace Milkcat {
	using namespace Math;
    typedef long long LL;
    typedef pair<LL, LL> pii;
    const int N = 305, mod = 998244353;
    typedef Mint<mod> MI;
    int n, m, x; MI ans;
	bitset<N> A[N];
	Combinations<MI> C;
    int main() {
		cin >> n >> m, C.init(n + m);
		REP(i, 1, n) REP(j, 1, m)
			cin >> x, A[i][j] = x;
		int r = 0;
		REP(k, 1, m) {
			int t = 0;
			REP(i, r + 1, n)
				if (A[i][k]) t = i;
			if (!t) continue;
			r ++, swap(A[r], A[t]);
			REP(i, 1, n)
				if (i != r && A[i][k]) A[i] ^= A[r];
		}
		REP(i, 0, r)
			if (i & 1) ans += C(r, i) * qpow((MI)3, r - i);
		cout << ans * qpow((MI)2, n + m - r * 2) << '\n';
        return 0;
    }
}
posted @ 2024-09-03 07:07  喵仔牛奶  阅读(17)  评论(0编辑  收藏  举报