題解:AT_yahoo_procon2019_qual_e Odd Subrectangles

喵仔牛奶發表於2024-09-03

怎麼題解全是線性基,來點高消做法。

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;
    }
}