Problem:
Problem I: Reverse Game
あるところにオセロが趣味な女の子がいました。時間があるときに家族とオセロを楽しんでいます。
ある日、女の子はいつものようにオセロで遊ぼうとしました。ところが、みんな忙しくて誰も遊んでくれませんでした。
そこでオセロのボードとこまを使って１人で遊べるゲームを考え出しました。
問題
縦\( R \)マス、横\( C \)マスのマス目全てにオセロの駒が上面が黒あるいは白になるように配置されている。
以下の図のように「あるマスを選んで、その上下左右斜め方向にある駒を全て裏返す」という操作を繰り返し行うことを考える。
全ての駒の上面を白にするような操作の仕方の個数を求めよ。 ただし、以下の条件を満たす必要がある。
同じマスに二度操作を行うことはできない
操作の順序は区別しない
全ての駒の上面が白になってから操作を続けることは可能である
入力
1行目に整数\( R \)と整数\( C \)がそれぞれ空白区切りで与えられる。
続けて\( R \)行に、それぞれ\( C \)個の整数値(0か1)が与えられる。\( r \)行目の\(
c \)個目の整数は、マス目(r,c)の状態を表す。
1は上面が黒であることを、0は上面が白であることを表す。
出力
盤面の全ての駒の上面を白にすることができるなら、そのような操作の仕方の個数を\(
1000000009 (= 10 ^ 9 + 9) \)で割った余りを1行に出力せよ。
盤面の全ての駒の上面を白にすることができないなら、\( 0 \)と1行に出力せよ。
制約
\(1 \leq R \leq 50, 1 \leq C \leq 50\)
サンプル入出力
入力1
1 3
1 1 1
出力1
4
\( \{(1,1)\}, \{(1,2)\}, \{(1,3)\}, \{(1,1),(1,2),(1,3)\} \)の4通りである。
入力2
1 3
1 0 1
出力2
0
入力3
2 4
0 1 0 1
1 0 1 0
出力3
1

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;

using wolf = unsigned long long;
constexpr int MOD = 1'000'000'009;
constexpr int MAXA = 110;
constexpr int MAXB = 110;
constexpr int MAXV = 2600; // a*b の最大
constexpr int WORDS = 42;  // 2600 / 64 ≈ 41

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int a, b;
    cin >> a >> b;

    vector<vector<int>> c(a, vector<int>(b));
    vector<array<wolf, WORDS>> s(a * b);

    for (int i = 0; i < a; i++) {
        for (int j = 0; j < b; j++) {
            cin >> c[i][j];
            s[i * b + j].fill(0);
            s[i * b + j][40] = c[i][j];
        }
    }

    // 制約を追加
    const wolf U = 1ULL;
    for (int i = 0; i < a; i++) {
        for (int j = 0; j < b; j++) {
            for (int k = 0; k < a; k++) {
                for (int l = 0; l < b; l++) {
                    if (i == k || j == l || (i + j) == (k + l) || (i - j) == (k - l)) {
                        int L = i * b + j;
                        int R = k * b + l;
                        s[L][R / 64] ^= (U << (R % 64));
                    }
                }
            }
        }
    }

    // 掃き出し法 (GF(2))
    int rank = 0;
    for (int i = 0; i < a * b; i++) {
        int pivot = -1;
        for (int j = rank; j < a * b; j++) {
            if (s[j][i / 64] & (U << (i % 64))) {
                pivot = j;
                break;
            }
        }
        if (pivot == -1) continue;

        swap(s[pivot], s[rank]);
        for (int j = rank + 1; j < a * b; j++) {
            if (s[j][i / 64] & (U << (i % 64))) {
                for (int k = 0; k < WORDS; k++) {
                    s[j][k] ^= s[rank][k];
                }
            }
        }
        rank++;
    }

    // 矛盾チェック
    bool ok = true;
    for (int i = 0; i < a * b; i++) {
        bool nonzero = false;
        for (int j = 0; j < 40; j++) {
            if (s[i][j]) {
                nonzero = true;
                break;
            }
        }
        if (!nonzero && s[i][40]) {
            ok = false;
            break;
        }
    }

    if (!ok) {
        cout << 0 << '\n';
        return 0;
    }

    // 解の個数は 2^(自由度)
    int free_vars = a * b - rank;
    long long result = 1;
    for (int i = 0; i < free_vars; i++) {
        result = (result * 2) % MOD;
    }
    cout << result << '\n';

    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 4224
final_rank: 1

code_snippet: #ifndef HIDDEN_IN_VS // 折りたたみ用

// 警告の抑制
#define _CRT_SECURE_NO_WARNINGS

// ライブラリの読み込み
#include <bits/stdc++.h>
using namespace std;

// 型名の短縮
using ll = long long; // -2^63 ～ 2^63 = 9 * 10^18（int は -2^31 ～ 2^31 = 2 * 10^9）
using pii = pair<int, int>;	using pll = pair<ll, ll>;	using pil = pair<int, ll>;	using pli = pair<ll, int>;
using vi = vector<int>;		using vvi = vector<vi>;		using vvvi = vector<vvi>;
using vl = vector<ll>;		using vvl = vector<vl>;		using vvvl = vector<vvl>;
using vb = vector<bool>;	using vvb = vector<vb>;		using vvvb = vector<vvb>;
using vc = vector<char>;	using vvc = vector<vc>;		using vvvc = vector<vvc>;
using vd = vector<double>;	using vvd = vector<vd>;		using vvvd = vector<vvd>;
using ld = long double; using vld = vector<ld>; using vvld = vector<vld>;
template <class T> using priority_queue_rev = priority_queue<T, vector<T>, greater<T>>;
using Graph = vvi;

// 定数の定義
const double PI = acos(-1);
const vi DX = { 1, 0, -1, 0 }; // 4 近傍（下，右，上，左）
const vi DY = { 0, 1, 0, -1 };
int INF = 1001001001; ll INFL = 4004004004004004004LL;
double EPS = 1e-12;

// 入出力高速化
struct fast_io { fast_io() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(18); } } fastIOtmp;

// 汎用マクロの定義
#define all(a) (a).begin(), (a).end()
#define sz(x) ((int)(x).size())
#define lbpos(a, x) (int)distance((a).begin(), std::lower_bound(all(a), x))
#define ubpos(a, x) (int)distance((a).begin(), std::upper_bound(all(a), x))
#define Yes(b) {cout << ((b) ? "Yes\n" : "No\n");}
#define rep(i, n) for(int i = 0, i##_len = int(n); i < i##_len; ++i) // 0 から n-1 まで昇順
#define repi(i, s, t) for(int i = int(s), i##_end = int(t); i <= i##_end; ++i) // s から t まで昇順
#define repir(i, s, t) for(int i = int(s), i##_end = int(t); i >= i##_end; --i) // s から t まで降順
#define repe(v, a) for(const auto& v : (a)) // a の全要素（変更不可能）
#define repea(v, a) for(auto& v : (a)) // a の全要素（変更可能）
#define repb(set, d) for(int set = 0; set < (1 << int(d)); ++set) // d ビット全探索（昇順）
#define repp(a) sort(all(a)); for(bool a##_perm = true; a##_perm; a##_perm = next_permutation(all(a))) // a の順列全て（昇順）
#define smod(n, m) ((((n) % (m)) + (m)) % (m)) // 非負mod
#define uniq(a) {sort(all(a)); (a).erase(unique(all(a)), (a).end());} // 重複除去
#define EXIT(a) {cout << (a) << endl; exit(0);} // 強制終了

// 汎用関数の定義
template <class T> inline ll pow(T n, int k) { ll v = 1; rep(i, k) v *= n; return v; }
template <class T> inline bool chmax(T& M, const T& x) { if (M < x) { M = x; return true; } return false; } // 最大値を更新（更新されたら true を返す）
template <class T> inline bool chmin(T& m, const T& x) { if (m > x) { m = x; return true; } return false; } // 最小値を更新（更新されたら true を返す）

// 演算子オーバーロード
template <class T, class U> inline istream& operator>>(istream& is, pair<T, U>& p) { is >> p.first >> p.second; return is; }
template <class T> inline istream& operator>>(istream& is, vector<T>& v) { repea(x, v) is >> x; return is; }
template <class T> inline vector<T>& operator--(vector<T>& v) { repea(x, v) --x; return v; }
template <class T> inline vector<T>& operator++(vector<T>& v) { repea(x, v) ++x; return v; }

// 手元環境（Visual Studio）
#ifdef _MSC_VER
#include "local.hpp"
// 提出用（gcc）
#else
inline int popcount(int n) { return __builtin_popcount(n); }
inline int popcount(ll n) { return __builtin_popcountll(n); }
inline int lsb(int n) { return n != 0 ? __builtin_ctz(n) : -1; }
inline int lsb(ll n) { return n != 0 ? __builtin_ctzll(n) : -1; }
inline int msb(int n) { return n != 0 ? (31 - __builtin_clz(n)) : -1; }
inline int msb(ll n) { return n != 0 ? (63 - __builtin_clzll(n)) : -1; }
#define gcd __gcd
#define dump(...)
#define dumpel(v)
#define dump_list(v)
#define input_from_file(f)
#define output_to_file(f)
#define Assert(b) { if (!(b)) while (1) cout << "OLE"; }
#endif

#endif // 折りたたみ用


////--------------AtCoder 専用--------------
//#include <atcoder/all>
//using namespace atcoder;
//
////using mint = modint1000000007;
//using mint = modint998244353;
////using mint = modint; // mint::set_mod(m);
//
//istream& operator>>(istream& is, mint& x) { ll x_; is >> x_; x = x_; return is; }
//ostream& operator<<(ostream& os, const mint& x) { os << x.val(); return os; }
//using vm = vector<mint>; using vvm = vector<vm>; using vvvm = vector<vvm>;
////----------------------------------------


//【ビット行列】
/*
* ビット行列を表す構造体
*
* Bit_matrix<N>(int m, int n) : O(m N / 64)
*	m * n 零行列で初期化する．
*	制約：n <= N
*
* Bit_matrix<N>(int n) : O(n N / 64)
*	n * n 単位行列で初期化する．
*
* Bit_matrix<N>(vector<bitset<N>> a, int n) : O(m N / 64)
*	配列 a の要素で初期化する．
*
* push_back(bitset<N> col) : O(N / 64)
*	最下行に col を追加する．
*
* A * x : O(m N / 64)
*	m * n 行列 A と n 次元列ベクトル x の積を返す．
*	制約：m <= N
*
* A * B : O(l m n)
*	l * m 行列 A と m * n 行列 B の積を返す．
*
* pow(ll d) : O(n^3 log d)
*	自身を d 乗した行列を返す．
*
* transpose() : O(m n)
*	自身を転置した行列を返す．
*/
template <int N> struct Bit_matrix {
	int m, n; // 行数, 列数（行列のサイズは m * n）
	vector<bitset<N>> v; // 行列の成分

	// コンストラクタ（初期化なし，零行列，単位行列，二次元配列）
	Bit_matrix() : m(0), n(0) {}
	Bit_matrix(int m_, int n_) : m(m_), n(n_), v(m) {}
	Bit_matrix(int n_) : m(n_), n(n_), v(m) { rep(i, n) v[i][i] = 1; }
	Bit_matrix(const vector<bitset<N>>& a, int n_) : m(sz(a)), n(n_), v(a) {}

	// 代入
	Bit_matrix(const Bit_matrix& old) = default;
	Bit_matrix& operator=(const Bit_matrix& other) = default;

	// 比較
	bool operator==(const Bit_matrix& g) const { return m == g.m && n == g.n && v == g.v; }
	bool operator!=(const Bit_matrix& g) const { return !(*this == g); }

	// アクセス
	bitset<N> const& operator[](int i) const { return v[i]; }
	bitset<N>& operator[](int i) { return v[i]; }

	// 行の追加
	void push_back(const bitset<N>& col) { v.push_back(col); m++; }

	// 行列ベクトル積
	bitset<N> operator*(const bitset<N>& x) const {
		bitset<N> y;
		rep(i, m) y[i] = (v[i] & x).count() % 2;
		return y;
	}

	// 積
	Bit_matrix operator*(const Bit_matrix& b) const {
		Bit_matrix res(m, b.n);
		rep(i, res.m) rep(j, res.n) rep(k, n) res[i][j] = res[i][j] ^ (v[i][k] & b[k][j]);
		return res;
	}
	Bit_matrix& operator*=(const Bit_matrix& b) { *this = *this * b; return *this; }

	// 累乗
	Bit_matrix pow(ll d) const {
		Bit_matrix res(n), pow2 = *this;
		while (d > 0) {
			if ((d & 1) != 0) res *= pow2;
			pow2 *= pow2;
			d /= 2;
		}
		return res;
	}

	// 転置（A^T）
	Bit_matrix transpose() const {
		Bit_matrix res(n, m);
		rep(i, res.m) rep(j, res.n) res[i][j] = v[j][i];
		return res;
	}

#ifdef _MSC_VER
	friend ostream& operator<<(ostream& os, const Bit_matrix& a) {
		rep(i, a.m) {
			rep(j, a.n) os << a.v[i][j] << " ";
			os << endl;
		}
		return os;
	}
#endif
};


//【行簡約階段形】O(m n min(m, n) / 64)
/*
* 行基本変形で m×n 行列 mat を行簡約階段形に変形する（ピボットの上下は全て 0．）
* また i 行目のピボットが何列目かを pjs[i] に格納し，mat の階数を返す．
*
*（呼び出すとき reduced_row_echelon_form<N> としないと gcc でエラーになるので注意．）
*/
template <int N> int reduced_row_echelon_form(Bit_matrix<N>& mat, vi* pjs = nullptr) {
	// verify : https://atcoder.jp/contests/abc249/tasks/abc249_g

	int m = mat.m, n = mat.n;
	if (pjs != nullptr) pjs->clear();

	// 注目位置を (i, j)（i 行目かつ j 列目）とする．
	int i = 0, j = 0;

	while (i < m && j < n) {
		// 注目列の下方の行から 1 を見つける．
		int i2 = i;
		while (i2 < m && !mat[i2][j]) i2++;

		// 見つからなかったら注目位置を右に移す．
		if (i2 == m) { j++; continue; }

		// 見つかったら i 行目とその行を入れ替える．
		swap(mat[i], mat[i2]);

		// i 行目以外の j 列目の成分が全て 0 になるよう XOR をとる．
		rep(i2, m) {
			if (i2 == i) continue;

			if (mat[i2][j]) mat[i2] ^= mat[i];
		}

		// ピボット位置の記録
		if (pjs != nullptr) pjs->push_back(j);

		// 注目位置を右下に移す．
		i++; j++;
	}

	return i;
}


ll pow_mod(ll x, ll n) {
	// verify : https://atcoder.jp/contests/abc013/tasks/abc013_4

	ll MOD = (ll)1e9 + 9;
	ll res(1), pow2 = x;
	while (n > 0) {
		if ((n & 1) != 0) res = res * pow2 % MOD;
		pow2 = pow2 * pow2 % MOD;
		n /= 2;
	}
	return res;
}


int main() {
//	input_from_file("input.txt");
//	output_to_file("output.txt");

	int h, w;
	cin >> h >> w;

	vvi s(h, vi(w));
	cin >> s;

	const int N = 2510;
	Bit_matrix<N> mat(h * w, h * w + 1);
	rep(x, h) rep(y, w) {
		// 押したマスは点灯状態が反転する．
		mat[x * w + y][x * w + y] = 1;

		// 押したマスの 8 近傍方向も点灯状態が反転する．
		repi(dx, -1, 1) repi(dy, -1, 1) {
			if (dx == 0 && dy == 0) continue;

			int nx = x + dx, ny = y + dy;
			while (true) {
				if (nx < 0 || h <= nx || ny < 0 || w <= ny) break;

				mat[x * w + y][nx * w + ny] = 1;
				nx += dx; ny += dy;
			}
		}

		// 目標とする点灯パターン
		mat[x * w + y][h * w] = s[x][y];
	}
	dump(mat);

	vi pjs;
	int r = reduced_row_echelon_form<N>(mat, &pjs);

	if (pjs.back() == h * w) EXIT(0);

	EXIT(pow_mod(2, h * w - r));
}
accuracy: 1
time_ms: 70
memory_kb: 4216
final_rank: 2

code_snippet: #include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif


#include <utility>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

struct barrett {
    unsigned int _m;
    unsigned long long im;

    explicit barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    unsigned int umod() const { return _m; }

    unsigned int mul(unsigned int a, unsigned int b) const {

        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned int v = (unsigned int)(z - x * _m);
        if (_m <= v) v += _m;
        return v;
    }
};

constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    constexpr long long bases[3] = {2, 7, 61};
    for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);

constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b


        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

unsigned long long floor_sum_unsigned(unsigned long long n,
                                      unsigned long long m,
                                      unsigned long long a,
                                      unsigned long long b) {
    unsigned long long ans = 0;
    while (true) {
        if (a >= m) {
            ans += n * (n - 1) / 2 * (a / m);
            a %= m;
        }
        if (b >= m) {
            ans += n * (b / m);
            b %= m;
        }

        unsigned long long y_max = a * n + b;
        if (y_max < m) break;
        n = (unsigned long long)(y_max / m);
        b = (unsigned long long)(y_max % m);
        std::swap(m, a);
    }
    return ans;
}

}  // namespace internal

}  // namespace atcoder


#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T> using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder


namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

  public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt(998244353);

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <deque>
#include <list>
#include <queue>
#include <stack>
#include <vector>
#include <utility>
#include <algorithm>
#include <map>
#include <set>
#include <complex>
#include <cmath>
#include <limits>
#include <climits>
#include <ctime>
#include <cassert>
#include <numeric>
#include <functional>
#include <bitset>
#include <cstddef>
#include <type_traits>
#include <vector>

using namespace std;
const long long int INF = numeric_limits<long long int>::max() / 4;
const int inf = numeric_limits<int>::max() / 4;
const long long int MOD1000000007 = 1000000007;
const long long int MOD998244353 = 998244353;
const double MATH_PI = 3.1415926535897932;

template<typename T1, typename T2>
inline void chmin(T1 &a, const T2 &b) { if (a > b) a = b; }

template<typename T1, typename T2>
inline void chmax(T1 &a, const T2 &b) { if (a < b) a = b; }

#define lint long long int
#define ALL(a) a.begin(),a.end()
#define RALL(a) a.rbegin(),a.rend()
#define rep(i, n) for(int i=0;i<(int)(n);i++)
#define VI vector<int>
#define VLL vector<long long>
#define VC vector<char>
#define VB vector<bool>
#define PI pair<int, int>
#define PLL pair<long long, long long>
#define VPI vector<pair<int, int>>
#define VPLL vector<pair<long long, long long>>
#define VVI vector<vector<int>>
#define VVPI vecor<vector<pair<int, int>>>
#define VVPILL vector<vector<pair<int, long long>>>

#define SUM(v) accumulate(ALL(v), 0LL)
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))


const int MAX_ROW = 2510; // to be set appropriately
const int MAX_COL = 2510; // to be set appropriately

struct BitMatrix {
    int H, W;
    bitset<MAX_COL> val[MAX_ROW];

    BitMatrix(int m = 1, int n = 1) : H(m), W(n) {}

    inline bitset<MAX_COL> &operator[](int i) { return val[i]; }
};

int GaussJordan(BitMatrix &A, bool is_extended = false) {
    int rank = 0;
    for (int col = 0; col < A.W; ++col) {
        if (is_extended && col == A.W - 1) break;
        int pivot = -1;
        for (int row = rank; row < A.H; ++row) {
            if (A[row][col]) {
                pivot = row;
                break;
            }
        }
        if (pivot == -1) continue;
        swap(A[pivot], A[rank]);
        for (int row = 0; row < A.H; ++row) {
            if (row != rank && A[row][col]) A[row] ^= A[rank];
        }
        ++rank;
    }
    return rank;
}

int linear_equation(BitMatrix A, vector<int> b, vector<int> &res) {
    int m = A.H, n = A.W;
    BitMatrix M(m, n + 1);
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) M[i][j] = A[i][j];
        M[i][n] = b[i];
    }
    int rank = GaussJordan(M, true);

    // check if it has no solution
    for (int row = rank; row < m; ++row) if (M[row][n]) return -1;

    // answer
    res.assign(n, 0);
    for (int i = 0; i < rank; ++i) res[i] = M[i][n];
    return rank;
}

using mint = atcoder::static_modint<1000000009>;

void f() {

    int h, w;
    cin >> h >> w;
    vector<vector<int>> s(h, vector<int>(w));
    rep (i, h) {
        rep (j, w) {
            cin >> s[i][j];
        }
    }

    int n = h * w;
    // cout << "n = " << n << endl;
    BitMatrix A(n, n);
    vector<int> b(n, 0);
    rep (i, h) {
        rep (j, w) {
            int mi = i * w + j;
            b[mi] = s[i][j];
            // A[mi][mi] = 1;
            rep (ii, h) {
                rep (jj, w) {
                    if (i == ii or j == jj or (i + j == ii + jj) or (i - j == ii - jj)) {
                        int mj = ii * w + jj;
                        A[mi][mj] = 1;
                    }
                }
            }
        }
    }

    vector<int> res;
    // for (int i = 0; i < n; i++) {
    //     for (int j = 0; j < n; j++) {
    //         cout << A[i][j] << " ";
    //     }
    //     cout << endl;
    // }
    // for (int i = 0; i < n; i++) {
    //     cout << b[i] << endl;
    // }
    int rank = linear_equation(A, b, res);
    if (rank == -1) {
        cout << 0 << endl;
    } else {
        cout << mint(2).pow(n - rank).val() << endl;
    }
}

int main() {

    f();
    return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 5840
final_rank: 8

code_snippet: #include<bits/stdc++.h>
using namespace std;

const int MAX_ROW = 2510; // to be set appropriately
const int MAX_COL = 2510; // to be set appropriately
struct BitMatrix {
    int H, W;
    bitset<MAX_COL> val[MAX_ROW];
    BitMatrix(int m = 1, int n = 1) : H(m), W(n) {}
    inline bitset<MAX_COL>& operator [] (int i) {return val[i];}
};

ostream& operator << (ostream& s, BitMatrix A) {
    s << endl; 
    for (int i = 0; i < A.H; ++i) {
        for (int j = 0; j < A.W; ++j) {
            s << A[i][j] << ", ";
        }
        s << endl;
    }
    return s;
}

inline BitMatrix operator * (BitMatrix A, BitMatrix B) {
    BitMatrix R(A.H, B.W);
    BitMatrix tB(B.W, B.H);
    for (int i = 0; i < tB.H; ++i) for (int j = 0; j < tB.W; ++j) tB[i][j] = B[j][i];
    for (int i = 0; i < R.H; ++i) for (int j = 0; j < R.W; ++j) R[i][j] = ((A[i] & tB[j]).count() & 1);
    return R;
}

inline BitMatrix pow(BitMatrix A, long long n) {
    BitMatrix R(A.H, A.H);
    for (int i = 0; i < A.H; ++i) R[i][i] = 1;
    while (n > 0) {
        if (n & 1) R = R * A;
        A = A * A;
        n >>= 1;
    }
    return R;
}

int GaussJordan(BitMatrix &A, bool is_extended = false) {
    int rank = 0;
    for (int col = 0; col < A.W; ++col) {
        if (is_extended && col == A.W - 1) break;
        int pivot = -1;
        for (int row = rank; row < A.H; ++row) {
            if (A[row][col]) {
                pivot = row;
                break;
            }
        }
        if (pivot == -1) continue;
        swap(A[pivot], A[rank]);
        for (int row = 0; row < A.H; ++row) {
            if (row != rank && A[row][col]) A[row] ^= A[rank];
        }
        ++rank;
    }
    return rank;
}

int linear_equation(BitMatrix A, vector<int> b, vector<int> &res) {
    int m = A.H, n = A.W;
    BitMatrix M(m, n + 1);
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) M[i][j] = A[i][j];
        M[i][n] = b[i];
    }
    int rank = GaussJordan(M, true);

    // check if it has no solution
    for (int row = rank; row < m; ++row) if (M[row][n]) return -1;

    // answer
    res.assign(n, 0);
    for (int i = 0; i < rank; ++i) res[i] = M[i][n];
    return rank;
}


const long long MOD = 1000000009;
long long modpow(long long a, long long n, long long mod) {
    long long res = 1;
    while (n > 0) {
        if (n & 1) res = res * a % mod;
        a = a * a % mod;
        n >>= 1;
    }
    return res;
}

void solve(){
    //input
    long long R,C;
    cin >> R >> C;
    long long i,j,k;
    int ban[R][C];
    for(i=0; i<R; i++){
        for(j=0; j<C; j++){
            cin >> ban[i][j];
        }
    }

    //calc
    vector<int> b;
    for(i=0; i<R; i++){
        for(j=0; j<C; j++){
            b.push_back(ban[i][j]);
        }
    }
    BitMatrix A(R*C,R*C);
    for(i=0; i<R*C; i++){
        for(j=0; j<R*C; j++){
            A[i][j]=0;
        }
    }
    long long k_min, k_max;
    for(i=0; i<R; i++){
        for(j=0; j<C; j++){
            for(k=0; k<R; k++){
                A[i*C+j][k*C+j]=1;
            }
            for(k=0; k<C; k++){
                A[i*C+j][i*C+k]=1;
            }
            k_min=-min(i,j);
            k_max=min(R-1-i,C-1-j);
            for(k=k_min; k<=k_max; k++){
                A[i*C+j][(i+k)*C+(j+k)]=1;
            }
            k_min=-min(i,C-1-j);
            k_max=min(R-1-i,j);
            for(k=k_min; k<=k_max; k++){
                A[i*C+j][(i+k)*C+(j-k)]=1;
            }
        }
    }
    vector<int> c;
    long long rk=linear_equation(A,b,c);
    long long ans;
    if(rk>=0){
        ans=1;
        for(i=0; i<R*C-rk; i++){
            ans*=2LL;
            ans%=MOD;
        }
    }else{
        ans=0;
    }

    //output
    cout << ans << endl;
}

int main(){
    solve();
    return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 5572
final_rank: 12

code_snippet: #include<bits/stdc++.h>
using namespace std;

const int MAX_ROW = 2510; // to be set appropriately
const int MAX_COL = 2510; // to be set appropriately
struct BitMatrix {
    int H, W;
    bitset<MAX_COL> val[MAX_ROW];
    BitMatrix(int m = 1, int n = 1) : H(m), W(n) {}
    inline bitset<MAX_COL>& operator [] (int i) {return val[i];}
};

ostream& operator << (ostream& s, BitMatrix A) {
    s << endl; 
    for (int i = 0; i < A.H; ++i) {
        for (int j = 0; j < A.W; ++j) {
            s << A[i][j] << ", ";
        }
        s << endl;
    }
    return s;
}

inline BitMatrix operator * (BitMatrix A, BitMatrix B) {
    BitMatrix R(A.H, B.W);
    BitMatrix tB(B.W, B.H);
    for (int i = 0; i < tB.H; ++i) for (int j = 0; j < tB.W; ++j) tB[i][j] = B[j][i];
    for (int i = 0; i < R.H; ++i) for (int j = 0; j < R.W; ++j) R[i][j] = ((A[i] & tB[j]).count() & 1);
    return R;
}

inline BitMatrix pow(BitMatrix A, long long n) {
    BitMatrix R(A.H, A.H);
    for (int i = 0; i < A.H; ++i) R[i][i] = 1;
    while (n > 0) {
        if (n & 1) R = R * A;
        A = A * A;
        n >>= 1;
    }
    return R;
}

int GaussJordan(BitMatrix &A, bool is_extended = false) {
    int rank = 0;
    for (int col = 0; col < A.W; ++col) {
        if (is_extended && col == A.W - 1) break;
        int pivot = -1;
        for (int row = rank; row < A.H; ++row) {
            if (A[row][col]) {
                pivot = row;
                break;
            }
        }
        if (pivot == -1) continue;
        swap(A[pivot], A[rank]);
        for (int row = 0; row < A.H; ++row) {
            if (row != rank && A[row][col]) A[row] ^= A[rank];
        }
        ++rank;
    }
    return rank;
}

int linear_equation(BitMatrix A, vector<int> b, vector<int> &res) {
    int m = A.H, n = A.W;
    BitMatrix M(m, n + 1);
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) M[i][j] = A[i][j];
        M[i][n] = b[i];
    }
    int rank = GaussJordan(M, true);

    // check if it has no solution
    for (int row = rank; row < m; ++row) if (M[row][n]) return -1;

    // answer
    res.assign(n, 0);
    for (int i = 0; i < rank; ++i) res[i] = M[i][n];
    return rank;
}


const long long MOD = 1000000007;
long long modpow(long long a, long long n, long long mod) {
    long long res = 1;
    while (n > 0) {
        if (n & 1) res = res * a % mod;
        a = a * a % mod;
        n >>= 1;
    }
    return res;
}

void solve(){
    //input
    long long R,C;
    cin >> R >> C;
    long long i,j,k;
    int ban[R][C];
    for(i=0; i<R; i++){
        for(j=0; j<C; j++){
            cin >> ban[i][j];
        }
    }

    //calc
    vector<int> b;
    for(i=0; i<R; i++){
        for(j=0; j<C; j++){
            b.push_back(ban[i][j]);
        }
    }
    BitMatrix A(R*C,R*C);
    for(i=0; i<R*C; i++){
        for(j=0; j<R*C; j++){
            A[i][j]=0;
        }
    }
    long long k_min, k_max;
    for(i=0; i<R; i++){
        for(j=0; j<C; j++){
            for(k=0; k<R; k++){
                A[i*C+j][k*C+j]=1;
            }
            for(k=0; k<C; k++){
                A[i*C+j][i*C+k]=1;
            }
            k_min=-min(i,j);
            k_max=min(R-1-i,C-1-j);
            for(k=k_min; k<=k_max; k++){
                A[i*C+j][(i+k)*C+(j+k)]=1;
            }
            k_min=-min(i,C-1-j);
            k_max=min(R-1-i,j);
            for(k=k_min; k<=k_max; k++){
                A[i*C+j][(i+k)*C+(j-k)]=1;
            }
        }
    }
    vector<int> c;
    long long rk=linear_equation(A,b,c);
    long long ans;
    if(rk>=0){
        ans=1;
        for(i=0; i<R*C-rk; i++){
            ans*=2LL;
            ans%=MOD;
        }
    }else{
        ans=0;
    }

    //output
    cout << ans << endl;
}

int main(){
    solve();
    return 0;
}
accuracy: 0.6615384615384615
time_ms: 60
memory_kb: 5528
final_rank: 19

code_snippet: #include<bits/stdc++.h>
using namespace std;

const int MAX_ROW = 2510; // to be set appropriately
const int MAX_COL = 2510; // to be set appropriately
struct BitMatrix {
    int H, W;
    bitset<MAX_COL> val[MAX_ROW];
    BitMatrix(int m = 1, int n = 1) : H(m), W(n) {}
    inline bitset<MAX_COL>& operator [] (int i) {return val[i];}
};

ostream& operator << (ostream& s, BitMatrix A) {
    s << endl; 
    for (int i = 0; i < A.H; ++i) {
        for (int j = 0; j < A.W; ++j) {
            s << A[i][j] << ", ";
        }
        s << endl;
    }
    return s;
}

inline BitMatrix operator * (BitMatrix A, BitMatrix B) {
    BitMatrix R(A.H, B.W);
    BitMatrix tB(B.W, B.H);
    for (int i = 0; i < tB.H; ++i) for (int j = 0; j < tB.W; ++j) tB[i][j] = B[j][i];
    for (int i = 0; i < R.H; ++i) for (int j = 0; j < R.W; ++j) R[i][j] = ((A[i] & tB[j]).count() & 1);
    return R;
}

inline BitMatrix pow(BitMatrix A, long long n) {
    BitMatrix R(A.H, A.H);
    for (int i = 0; i < A.H; ++i) R[i][i] = 1;
    while (n > 0) {
        if (n & 1) R = R * A;
        A = A * A;
        n >>= 1;
    }
    return R;
}

int GaussJordan(BitMatrix &A, bool is_extended = false) {
    int rank = 0;
    for (int col = 0; col < A.W; ++col) {
        if (is_extended && col == A.W - 1) break;
        int pivot = -1;
        for (int row = rank; row < A.H; ++row) {
            if (A[row][col]) {
                pivot = row;
                break;
            }
        }
        if (pivot == -1) continue;
        swap(A[pivot], A[rank]);
        for (int row = 0; row < A.H; ++row) {
            if (row != rank && A[row][col]) A[row] ^= A[rank];
        }
        ++rank;
    }
    return rank;
}

int linear_equation(BitMatrix A, vector<int> b, vector<int> &res) {
    int m = A.H, n = A.W;
    BitMatrix M(m, n + 1);
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) M[i][j] = A[i][j];
        M[i][n] = b[i];
    }
    int rank = GaussJordan(M, true);

    // check if it has no solution
    for (int row = rank; row < m; ++row) if (M[row][n]) return -1;

    // answer
    res.assign(n, 0);
    for (int i = 0; i < rank; ++i) res[i] = M[i][n];
    return rank;
}


const long long MOD = 1000000007;
long long modpow(long long a, long long n, long long mod) {
    long long res = 1;
    while (n > 0) {
        if (n & 1) res = res * a % mod;
        a = a * a % mod;
        n >>= 1;
    }
    return res;
}

void solve(){
    //input
    long long R,C;
    cin >> R >> C;
    long long i,j,k;
    int ban[R][C];
    for(i=0; i<R; i++){
        for(j=0; j<C; j++){
            cin >> ban[i][j];
        }
    }

    //calc
    vector<int> b;
    for(i=0; i<R; i++){
        for(j=0; j<C; j++){
            b.push_back(ban[i][j]);
        }
    }
    BitMatrix A(R*C,R*C);
    for(i=0; i<R*C; i++){
        for(j=0; j<R*C; j++){
            A[i][j]=0;
        }
    }
    long long k_min, k_max;
    for(i=0; i<R; i++){
        for(j=0; j<C; j++){
            for(k=0; k<R; k++){
                A[i*C+j][k*C+j]=1;
            }
            for(k=0; k<C; k++){
                A[i*C+j][i*C+k]=1;
            }
            k_min=-min(i,j);
            k_max=min(R-1-i,C-1-j);
            for(k=k_min; k<=k_max; k++){
                A[i*C+j][(i+k)*C+(j+k)]=1;
            }
            k_min=-min(i,C-1-j);
            k_max=min(R-1-i,j);
            for(k=k_min; k<=k_max; k++){
                A[i*C+j][(i+k)*C+(j-k)]=1;
            }
        }
    }
    vector<int> c;
    long long rk=linear_equation(A,b,c);
    long long ans;
    if(rk>=0){
        ans=1;
        for(i=0; i<R*C-rk; i++){
            ans*=2;
            ans%=MOD;
        }
    }else{
        ans=0;
    }

    //output
    cout << ans << endl;
}

int main(){
    solve();
    return 0;
}
accuracy: 0.6615384615384615
time_ms: 60
memory_kb: 5536
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;

template<int n>
struct bitMatrix {
  int h, w;
  vector<bitset<n>> bits;
  bitMatrix():h(0), w(0), bits(h) {}
  bitMatrix(int n_):h(n_), w(n_), bits(h) {} 
  bitMatrix(int h_, int w_):h(h_), w(w_), bits(h) {}
  const bitset<n> &operator[](int i) const {return bits[i];}
  bitset<n> &operator[](int i) {return bits[i];}
	static bitMatrix I(int siz) {
		bitMatrix x(siz);
		for(int i = 0; i < siz; i++) x[i].set(i);
		return x;
	}
	bitMatrix &operator*=(const bitMatrix &rhs) {
    int rh = rhs.h, rw = rhs.w;
		assert(w == rh);
    bitMatrix res(h, rw), trhs(rw, rh);
    for(int i = 0; i < rw; i++) {
      for(int j = 0; j < rh; j++) {
        trhs[i][j] = rhs[j][i];
      }
    }
    for(int i = 0; i < h; i++) {
      for(int j = 0; j < rw; j++) {
        res[i][j] = ((bits[i]&trhs[j]).count() & 1);
      }
    }
    return res;
	}
	template<class T>
	bitMatrix &operator^=(T p) {
		assert(0 <= p and h == w);
		bitMatrix x = I(h);
		while(p) {
			if(p&1) x *= *this;
			*this *= *this;
			p >>= 1;
		}
    bits.swap(x.bits);
		return *this;
	}
  //for debug
  friend ostream &operator<<(ostream &os, const bitMatrix &p) {
    for(int i = 0; i < p.h; i++) {
			os << "[";
			for(int j = 0; j < p.w; j++) {
				os << p[i][j] << (j == p.w-1 ? "]\n":",");
			}
		}
		return os;
  }
};

template<int n>
int GaussJordan(bitMatrix<n> &A, bool is_extended = false) {
  int rank = 0;
  for(int col = 0; col < A.w; col++) {
    if(is_extended and col == A.w-1) break;
    int pivot = -1;
    for(int row = rank; row < A.h; row++) {
      if(A[row].test(col)) {
        pivot = row;
        break;
      }
    }
    if(pivot == -1) continue;
    swap(A[pivot], A[rank]);
    for(int row = 0; row < A.h; row++) {
      if(row != rank and A[row].test(col)) A[row] ^= A[rank];
    }
    rank++;
  }
  return rank;
}

template<int n_>
vector<int> linear_equation(const bitMatrix<n_> &A, const vector<int> &b) {
  int m = A.h, n = A.w;
  bitMatrix<n_> M(m, n+1);
  for(int i = 0; i < m; i++) {
    for(int j = 0; j < n; j++) M[i][j] = A[i][j];
    M[i][n] = b[i];
  }
  int rank = GaussJordan(M, true);
  vector<int> res;
  //解なし？
  for(int row = rank; row < m; row++) {
    if(M[row].test(n)) return res;
  }
  res.resize(rank);
  for(int i = 0; i < rank; i++) res[i] = M[i][n];
  return res;
}

struct barrett {
	unsigned int _m;
	uint64_t im;
	barrett(unsigned int m):_m(m), im(uint64_t(-1)/m + 1) {}
	unsigned int umod() const {return _m;}
	unsigned int mul(unsigned int a, unsigned int b) const {
		uint64_t z = a;
		z *= b;
		uint64_t x = uint64_t(((unsigned __int128)(z)*im) >> 64);
		unsigned int v = (unsigned int)(z-x*_m);
		if(_m <= v) v += _m;
		return v;
	}
};

constexpr int64_t safe_mod(int64_t x, int64_t m) {
	x %= m;
	if(x < 0) x += m;
	return x;
}

constexpr pair<int64_t, int64_t> inv_gcd(int64_t a, int64_t b) {
	a = safe_mod(a, b);
	if(a == 0) return {b, 0};
	int64_t s = b, t = a;
	int64_t m0 = 0, m1 = 1;
	while(t) {
		int64_t u = s/t;
		s -= t*u;
		m0 -= m1*u;
		int64_t tmp = s;
		s = t;
		t = tmp;
		tmp = m0;
		m0 = m1;
		m1 = tmp;
	}
	if(m0 < 0) m0 += b/s;
	return {s, m0};
}

int64_t pow_mod(int64_t x, int64_t n, int m) {
	if(m == 1) return 0;
	barrett bt((unsigned int)(m));
	unsigned int r = 1, y = (unsigned int)(safe_mod(x, m));
	while(n) {
		if(n&1) r = bt.mul(r, y);
		y = bt.mul(y, y);
		n >>= 1;
	}
	return r;
}

int64_t inv_mod(int64_t x, int64_t m) {
	pair<int64_t, int64_t> z = inv_gcd(x, m);
	assert(z.first == 1);
	return z.second;
}

//(y, z) answer mod z = y, 無理な時は(-1, -1)
pair<int64_t, int64_t> crt(const vector<int64_t> &r, const vector<int64_t> &m) {
	int n = int(r.size());
	int64_t r0 = 0, m0 = 1;
	for(int i = 0; i < n; i++) {
		assert(1 <= m[i]);
		int64_t r1 = safe_mod(r[i], m[i]), m1 = m[i];
		if(m0 < m1) {
			swap(r0, r1);
			swap(m0, m1);
		}
		if(m0 % m1 == 0) {
			if(r0 % m1 != r1) return {-1, -1};
			continue;
		}
		int64_t g, im;
		tie(g, im) = inv_gcd(m0, m1);
		int64_t u1 = (m1/g);
		if((r1-r0)%g) return {-1, -1};
		int64_t x = (r1-r0)/g%u1 * im % u1;
		r0 += x*m0;
		m0 *= u1;
		if(r0 < 0) r0 += m0;
	}
	return {r0, m0};
}

//[0, n) (a*i+b)/m
int64_t floor_sum(int64_t n, int64_t m, int64_t a, int64_t b) {
	int64_t ans = 0;
	if(a >= m) {
		ans += ((n-1)*n>>1)*(a/m);
		a %= m;
	}
	if(b >= m) {
		ans += n*(b/m);
		b %= m;
	}
	int64_t y_max = (a*n+b)/m, x_max = y_max*m-b;
	if(y_max == 0) return ans;
	ans += (n - (x_max+a-1)/a) * y_max;
	ans += floor_sum(y_max, a, m, (a - x_max%a)%a);
	return ans;
}

int main() {
	int r, c;
	cin >> r >> c;
	bitMatrix<2550> mat(r*c);
	auto num = [&](int i, int j) {return i*c+j;};
	vector<int> b(r*c);
	for(int i = 0; i < r; i++) {
		for(int j = 0; j < c; j++) {
			cin >> b[num(i, j)];
			int x = num(i, j);
			for(int k = 0; k < r; k++) mat[num(k, j)].set(x);
			for(int k = 0; k < c; k++) mat[num(i, k)].set(x);
			for(int k = 1; i-k >= 0 and j-k >= 0; k++) mat[num(i-k, j-k)].set(x);
			for(int k = 1; i-k >= 0 and j+k < c; k++) mat[num(i-k, j+k)].set(x);
			for(int k = 1; i+k < r and j-k >= 0; k++) mat[num(i+k, j-k)].set(x);
			for(int k = 1; i+k < r and j+k < c; k++) mat[num(i+k, j+k)].set(x);
		}
	}
	auto v = linear_equation(mat, b);
	if(v.empty()) {
		cout << 0 << endl;
		return 0;
	}
	cout << pow_mod(2, r*c-int(v.size()), 1000000009) << endl;
}
accuracy: 1
time_ms: 90
memory_kb: 4664
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;

template<int n>
struct bitMatrix {
  int h, w;
  vector<bitset<n>> bits;
  bitMatrix():h(0), w(0), bits(h) {}
  bitMatrix(int n_):h(n_), w(n_), bits(h) {} 
  bitMatrix(int h_, int w_):h(h_), w(w_), bits(h) {}
  const bitset<n> &operator[](int i) const {return bits[i];}
  bitset<n> &operator[](int i) {return bits[i];}
	static bitMatrix I(int siz) {
		bitMatrix x(siz);
		for(int i = 0; i < siz; i++) x[i].set(i);
		return x;
	}
	bitMatrix &operator*=(const bitMatrix &rhs) {
    int rh = rhs.h, rw = rhs.w;
		assert(w == rh);
    bitMatrix res(h, rw), trhs(rw, rh);
    for(int i = 0; i < rw; i++) {
      for(int j = 0; j < rh; j++) {
        trhs[i][j] = rhs[j][i];
      }
    }
    for(int i = 0; i < h; i++) {
      for(int j = 0; j < rw; j++) {
        res[i][j] = ((bits[i]&trhs[j]).count() & 1);
      }
    }
    return res;
	}
	template<class T>
	bitMatrix &operator^=(T p) {
		assert(0 <= p and h == w);
		bitMatrix x = I(h);
		while(p) {
			if(p&1) x *= *this;
			*this *= *this;
			p >>= 1;
		}
    bits.swap(x.bits);
		return *this;
	}
  //for debug
  friend ostream &operator<<(ostream &os, const bitMatrix &p) {
    for(int i = 0; i < p.h; i++) {
			os << "[";
			for(int j = 0; j < p.w; j++) {
				os << p[i][j] << (j == p.w-1 ? "]\n":",");
			}
		}
		return os;
  }
};

template<int n>
int GaussJordan(bitMatrix<n> &A, bool is_extended = false) {
  int rank = 0;
  for(int col = 0; col < A.w; col++) {
    if(is_extended and col == A.w-1) break;
    int pivot = -1;
    for(int row = rank; row < A.h; row++) {
      if(A[row].test(col)) {
        pivot = row;
        break;
      }
    }
    if(pivot == -1) continue;
    swap(A[pivot], A[rank]);
    for(int row = 0; row < A.h; row++) {
      if(row != rank and A[row].test(col)) A[row] ^= A[rank];
    }
    rank++;
  }
  return rank;
}

template<int n_>
vector<int> linear_equation(const bitMatrix<n_> &A, const vector<int> &b) {
  int m = A.h, n = A.w;
  bitMatrix<n_> M(m, n+1);
  for(int i = 0; i < m; i++) {
    for(int j = 0; j < n; j++) M[i][j] = A[i][j];
    M[i][n] = b[i];
  }
  int rank = GaussJordan(M, true);
  vector<int> res;
  //解なし？
  for(int row = rank; row < m; row++) {
    if(M[row].test(n)) return res;
  }
  res.resize(rank);
  for(int i = 0; i < rank; i++) res[i] = M[i][n];
  return res;
}

struct barrett {
	unsigned int _m;
	uint64_t im;
	barrett(unsigned int m):_m(m), im(uint64_t(-1)/m + 1) {}
	unsigned int umod() const {return _m;}
	unsigned int mul(unsigned int a, unsigned int b) const {
		uint64_t z = a;
		z *= b;
		uint64_t x = uint64_t(((unsigned __int128)(z)*im) >> 64);
		unsigned int v = (unsigned int)(z-x*_m);
		if(_m <= v) v += _m;
		return v;
	}
};

constexpr int64_t safe_mod(int64_t x, int64_t m) {
	x %= m;
	if(x < 0) x += m;
	return x;
}

constexpr pair<int64_t, int64_t> inv_gcd(int64_t a, int64_t b) {
	a = safe_mod(a, b);
	if(a == 0) return {b, 0};
	int64_t s = b, t = a;
	int64_t m0 = 0, m1 = 1;
	while(t) {
		int64_t u = s/t;
		s -= t*u;
		m0 -= m1*u;
		int64_t tmp = s;
		s = t;
		t = tmp;
		tmp = m0;
		m0 = m1;
		m1 = tmp;
	}
	if(m0 < 0) m0 += b/s;
	return {s, m0};
}

int64_t pow_mod(int64_t x, int64_t n, int m) {
	if(m == 1) return 0;
	barrett bt((unsigned int)(m));
	unsigned int r = 1, y = (unsigned int)(safe_mod(x, m));
	while(n) {
		if(n&1) r = bt.mul(r, y);
		y = bt.mul(y, y);
		n >>= 1;
	}
	return r;
}

int64_t inv_mod(int64_t x, int64_t m) {
	pair<int64_t, int64_t> z = inv_gcd(x, m);
	assert(z.first == 1);
	return z.second;
}

//(y, z) answer mod z = y, 無理な時は(-1, -1)
pair<int64_t, int64_t> crt(const vector<int64_t> &r, const vector<int64_t> &m) {
	int n = int(r.size());
	int64_t r0 = 0, m0 = 1;
	for(int i = 0; i < n; i++) {
		assert(1 <= m[i]);
		int64_t r1 = safe_mod(r[i], m[i]), m1 = m[i];
		if(m0 < m1) {
			swap(r0, r1);
			swap(m0, m1);
		}
		if(m0 % m1 == 0) {
			if(r0 % m1 != r1) return {-1, -1};
			continue;
		}
		int64_t g, im;
		tie(g, im) = inv_gcd(m0, m1);
		int64_t u1 = (m1/g);
		if((r1-r0)%g) return {-1, -1};
		int64_t x = (r1-r0)/g%u1 * im % u1;
		r0 += x*m0;
		m0 *= u1;
		if(r0 < 0) r0 += m0;
	}
	return {r0, m0};
}

//[0, n) (a*i+b)/m
int64_t floor_sum(int64_t n, int64_t m, int64_t a, int64_t b) {
	int64_t ans = 0;
	if(a >= m) {
		ans += ((n-1)*n>>1)*(a/m);
		a %= m;
	}
	if(b >= m) {
		ans += n*(b/m);
		b %= m;
	}
	int64_t y_max = (a*n+b)/m, x_max = y_max*m-b;
	if(y_max == 0) return ans;
	ans += (n - (x_max+a-1)/a) * y_max;
	ans += floor_sum(y_max, a, m, (a - x_max%a)%a);
	return ans;
}

int main() {
	int r, c;
	cin >> r >> c;
	bitMatrix<2500> mat(r*c);
	auto num = [&](int i, int j) {return i*c+j;};
	vector<int> b(r*c);
	for(int i = 0; i < r; i++) {
		for(int j = 0; j < c; j++) {
			cin >> b[num(i, j)];
			int x = num(i, j);
			for(int k = 0; k < r; k++) mat[num(k, j)].set(x);
			for(int k = 0; k < c; k++) mat[num(i, k)].set(x);
			for(int k = 1; i-k >= 0 and j-k >= 0; k++) mat[num(i-k, j-k)].set(x);
			for(int k = 1; i-k >= 0 and j+k < c; k++) mat[num(i-k, j+k)].set(x);
			for(int k = 1; i+k < r and j-k >= 0; k++) mat[num(i+k, j-k)].set(x);
			for(int k = 1; i+k < r and j+k < c; k++) mat[num(i+k, j+k)].set(x);
		}
	}
	auto v = linear_equation(mat, b);
	if(v.empty()) {
		cout << 0 << endl;
		return 0;
	}
	cout << pow_mod(2, r*c-int(v.size()), 1000000009) << endl;
}
accuracy: 0.823076923076923
time_ms: 50
memory_kb: 4428
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for(int i = 0; i < n; i++)
#define rep2(i, x, n) for(int i = x; i <= n; i++)
#define rep3(i, x, n) for(int i = x; i >= n; i--)
#define elif else if
#define sp(x) fixed << setprecision(x)
#define pb push_back
#define eb emplace_back
#define all(x) x.begin(), x.end()
#define sz(x) (int)x.size()
using ll = long long;
using pii = pair<int, int>;
using pil = pair<int, ll>;
using pli = pair<ll, int>;
using pll = pair<ll, ll>;
const ll MOD = 1000000009;
//const ll MOD = 998244353;
const int inf = (1<<30)-1;
const ll INF = (1LL<<60)-1;
const double pi = acos(-1.0);
const double EPS = 1e-10;
template<typename T> bool chmax(T &x, const T &y) {return (x < y)? (x = y, true) : false;};
template<typename T> bool chmin(T &x, const T &y) {return (x > y)? (x = y, true) : false;};

template<ll mod>
struct Mod_Int{
    ll x;
    Mod_Int() {}
    Mod_Int(ll y) : x (y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

    Mod_Int &operator += (const Mod_Int &p){
        x = (x + p.x) % mod;
        return *this;
    }

    Mod_Int &operator -= (const Mod_Int &p){
        x = (x + mod - p.x) % mod;
        return *this;
    }

    Mod_Int &operator *= (const Mod_Int &p){
        x = (x * p.x) % mod;
        return *this;
    }

    Mod_Int &operator /= (const Mod_Int &p){
        *this *= p.inverse();
        return *this;
    }

    Mod_Int &operator ++ () {return *this += Mod_Int(1);}

    Mod_Int operator ++ (int){
        Mod_Int tmp = *this;
        ++*this;
        return tmp;
    }

    Mod_Int &operator -- () {return *this -= Mod_Int(1);}

    Mod_Int operator -- (int){
        Mod_Int tmp = *this;
        --*this;
        return tmp;
    }

    Mod_Int operator - () const {return Mod_Int(-x);}

    Mod_Int operator + (const Mod_Int &p) const {return Mod_Int(*this) += p;}

    Mod_Int operator - (const Mod_Int &p) const {return Mod_Int(*this) -= p;}

    Mod_Int operator * (const Mod_Int &p) const {return Mod_Int(*this) *= p;}

    Mod_Int operator / (const Mod_Int &p) const {return Mod_Int(*this) /= p;}

    bool operator == (const Mod_Int &p) const {return x == p.x;}

    bool operator != (const Mod_Int &p) const {return x != p.x;}

    Mod_Int inverse() const {return pow(mod-2);}

    Mod_Int pow(ll k) const{
        Mod_Int now = *this, ret = 1;
        while(k){
            if(k&1) ret *= now;
            now *= now, k >>= 1;
        }
        return ret;
    }

    friend ostream &operator << (ostream &os, const Mod_Int &p){
        return os << p.x;
    }

    friend istream &operator >> (istream &is, Mod_Int &p){
        ll a;
        is >> a;
        p = Mod_Int<mod>(a);
        return is;
    }
};

using mint = Mod_Int<MOD>;

template<typename T>
struct F2_Matrix{
    vector<T> A;

    F2_Matrix(int n) : A(n) {}

    int height() const {return sz(A);}

    int width() const {return sz(A.front());}

    inline const T &operator [] (int k) const{
        return A[k];
    }

    inline T &operator [] (int k){
        return A[k];
    }

    int normalize(){
        int n = height(), m = width(), check = 0, ret = 0;
        rep(j, m){
            int pivot = check;
            rep2(i, check, n-1){
                if(A[i][j]) pivot = i;
            }
            swap(A[check], A[pivot]);
            if(!A[check][j]) continue;
            ret++;
            rep(i, n){
                if(i == check || !A[i][j]) continue;
                A[i] ^= A[check];
            }
            if(++check == n) break;
        }
        return ret;
    }
};

int main(){
    int H, W;
    cin >> H >> W;
    F2_Matrix<bitset<2501>> A(H*W);
    rep(i, H){
        rep(j, W){
            bitset<2501> bs;
            int a; cin >> a;
            if(a) bs.set(H*W);
            rep(k, H){
                rep(l, W){
                    if(i == k || j == l || abs(i-k) == abs(j-l)) bs.set(W*k+l);
                }
            }
            A[W*i+j] = bs;
        }
    }
    int k = A.normalize();
    bitset<2501> ng;
    ng.set(H*W);
    rep(i, H*W){
        if(A[i] == ng) {cout << 0 << endl; return 0;}
    }
    cout << mint(2).pow(H*W-k) << endl;
}
accuracy: 1
time_ms: 100
memory_kb: 3640
final_rank: 4

code_snippet: #include <iostream>
#include <vector>
#include <array>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <string>
#include <sstream>
#include <algorithm>
#include <random>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cmath>
#include <cassert>
#include <climits>
#include <bitset>
#include <functional>
#include <iomanip>
#include <random>

#define FOR_LT(i, beg, end) for (int i = (int)(beg); i < (int)(end); i++)
#define FOR_LE(i, beg, end) for (int i = (int)(beg); i <= (int)(end); i++)
#define FOR_DW(i, beg, end) for (int i = (int)(beg); (int)(end) <= i; i--)
#define REP(n)              for (int repeat_index = 0; repeat_index < (int)n; repeat_index++)

using namespace std;

const int MAX_ROW = 2510; // to be set appropriately
const int MAX_COL = 2510; // to be set appropriately
struct BitMatrix {
    int H, W;
    bitset<MAX_COL> val[MAX_ROW];
    BitMatrix(int m = 1, int n = 1) : H(m), W(n) {}
    inline bitset<MAX_COL>& operator [] (int i) { return val[i]; }
};

int GaussJordan(BitMatrix& A, bool is_extended = false) {
    int rank = 0;
    for (int col = 0; col < A.W; ++col) {
        if (is_extended && col == A.W - 1) break;
        int pivot = -1;
        for (int row = rank; row < A.H; ++row) {
            if (A[row][col]) {
                pivot = row;
                break;
            }
        }
        if (pivot == -1) continue;
        swap(A[pivot], A[rank]);
        for (int row = 0; row < A.H; ++row) {
            if (row != rank && A[row][col]) A[row] ^= A[rank];
        }
        ++rank;
    }
    return rank;
}

BitMatrix M(2510, 2510);

int linear_equation(BitMatrix& A, vector<int>& b, vector<int>& res) {
    int m = A.H, n = A.W;
    M.H = m;
    M.W = n + 1;
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) M[i][j] = A[i][j];
        M[i][n] = b[i];
    }
    int rank = GaussJordan(M, true);

    // check if it has no solution
    for (int row = rank; row < m; ++row) if (M[row][n]) return -1;

    // answer
    res.assign(n, 0);
    for (int i = 0; i < rank; ++i) res[i] = M[i][n];
    return rank;
}

void setA(BitMatrix& A, int h, int w, int ox, int oy, int x, int y, int dir)
{
    int dirs[8][2] = {
        {1, 0},
        {-1, 0},
        {0, 1},
        {0, -1},
        {1, 1},
        {1, -1},
        {-1, 1},
        {-1, -1 },
    };

    int cx = x + dirs[dir][0];
    int cy = y + dirs[dir][1];

    if (cx < 0 || w <= cx || cy < 0 || h <= cy) {
        return;
    }

    int po =oy * w + ox;
    int p = cy * w + cx;
    A[po][p] = 1;
    setA(A, h, w, ox, oy, cx, cy, dir);
}

int64_t pow_rem(int64_t x, int64_t m, int64_t rem)
{
    if (m == 0) {
        return 1;
    }
    if (m == 1) {
        return x;
    }

    if (m & 1) {
        int64_t val = pow_rem(x, m / 2, rem);
        val = val * val;
        val %= rem;
        val *= x;
        val %= rem;
        return val;
    }
    else {
        int64_t val = pow_rem(x, m / 2, rem);
        val = val * val;
        val %= rem;
        return val;
    }
}
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout << fixed << setprecision(20);

    int h, w; cin >> h >> w;
    int n = h * w;

    BitMatrix A(n, n);
    {
        FOR_LT(y, 0, h) {
            FOR_LT(x, 0, w) {
                int p = y * w + x;
                A[p][p] = 1;
                FOR_LT(i, 0, 8) {
                    setA(A, h, w, x, y, x, y, i);
                }
            }
        }
    }

    vector<int> b(n);
    {
        FOR_LT(y, 0, h) {
            FOR_LT(x, 0, w) {
                int p = y * w + x;
                int f; cin >> f;
                if (f) b[p] = 1;
            }
        }
    }

    vector<int> res(n);
    int r = linear_equation(A, b, res);
    if (r == -1) {
        cout << 0 << endl;
        return 0;
    }

    cout << pow_rem(2, n - r, 1000000009) << endl;

    return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 4796
final_rank: 6

code_snippet: #define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;
#define FOR(i,m,n) for(int i=(m);i<(n);++i)
#define REP(i,n) FOR(i,0,n)
#define ALL(v) (v).begin(),(v).end()
using ll = long long;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3fLL;
const double EPS = 1e-8;
const int MOD = 1000000007;
// const int MOD = 998244353;
const int dy[] = {1, 0, -1, 0}, dx[] = {0, -1, 0, 1};
const int dy8[] = {1, 1, 0, -1, -1, -1, 0, 1}, dx8[] = {0, -1, -1, -1, 0, 1, 1, 1};
template <typename T, typename U> inline bool chmax(T &a, U b) { return a < b ? (a = b, true) : false; }
template <typename T, typename U> inline bool chmin(T &a, U b) { return a > b ? (a = b, true) : false; }
struct IOSetup {
  IOSetup() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(20);
  }
} iosetup;

template <int COL = 2500>
struct BinaryMatrix {
  int m, n;

  BinaryMatrix(int m, int n = COL, bool def = false) : m(m), n(n), dat(m, bitset<COL>(0)) {
    if (def) {
      REP(i, m) REP(j, n) dat[i][j] = 1;
    }
  }

  BinaryMatrix pow(ll exponent) {
    BinaryMatrix tmp = *this, res(n, n);
    REP(i, n) res[i][i] = 1;
    while (exponent > 0) {
      if (exponent & 1) res *= tmp;
      tmp *= tmp;
      exponent >>= 1;
    }
    return res;
  }

  inline const bitset<COL> &operator[](const int idx) const { return dat[idx]; }
  inline bitset<COL> &operator[](const int idx) { return dat[idx]; }

  BinaryMatrix &operator=(const BinaryMatrix &x) {
    m = x.m;
    n = x.n;
    dat.resize(m);
    REP(i, m) dat[i] = x[i];
    return *this;
  }

  BinaryMatrix &operator+=(const BinaryMatrix &x) {
    REP(i, m) dat[i] ^= x[i];
    return *this;
  }

  BinaryMatrix &operator*=(const BinaryMatrix &x) {
    int height = m, width = x.n;
    BinaryMatrix t_x(x.n, x.m), res(height, width);
    REP(i, x.n) REP(j, x.m) t_x[i][j] = x[j][i];
    REP(i, height) REP(j, width) res[i][j] = ((dat[i] & t_x[j]).count() & 1);
    *this = res;
    return *this;
  }

  BinaryMatrix operator+(const BinaryMatrix &x) const { return BinaryMatrix(*this) += x; }

  BinaryMatrix operator*(const BinaryMatrix &x) const { return BinaryMatrix(*this) *= x; }

private:
  vector<bitset<COL> > dat;
};

template <int COL>
int gauss_jordan(BinaryMatrix<COL> &mat, bool is_extended = false) {
  int rank = 0;
  REP(col, mat.n) {
    if (is_extended && col == mat.n - 1) break;
    int pivot = -1;
    FOR(row, rank, mat.m) {
      if (mat[row][col]) {
        pivot = row;
        break;
      }
    }
    if (pivot == -1) continue;
    swap(mat[rank], mat[pivot]);
    REP(row, mat.m) {
      if (row != rank && mat[row][col]) mat[row] ^= mat[rank];
    }
    ++rank;
  }
  return rank;
}

int mod = 1000000009;
struct ModInt {
  unsigned val;
  ModInt(): val(0) {}
  ModInt(ll x) : val(x >= 0 ? x % mod : x % mod + mod) {}
  ModInt pow(ll exponent) {
    ModInt tmp = *this, res = 1;
    while (exponent > 0) {
      if (exponent & 1) res *= tmp;
      tmp *= tmp;
      exponent >>= 1;
    }
    return res;
  }
  ModInt &operator+=(const ModInt &x) { if((val += x.val) >= mod) val -= mod; return *this; }
  ModInt &operator-=(const ModInt &x) { if((val += mod - x.val) >= mod) val -= mod; return *this; }
  ModInt &operator*=(const ModInt &x) { val = static_cast<unsigned long long>(val) * x.val % mod; return *this; }
  ModInt &operator/=(const ModInt &x) {
    // assert(__gcd(static_cast<int>(x.val), mod) == 1);
    unsigned a = x.val, b = mod; int u = 1, v = 0;
    while (b) {
      unsigned tmp = a / b;
      swap(a -= tmp * b, b);
      swap(u -= tmp * v, v);
    }
    return *this *= u;
  }
  bool operator==(const ModInt &x) const { return val == x.val; }
  bool operator!=(const ModInt &x) const { return val != x.val; }
  bool operator<(const ModInt &x) const { return val < x.val; }
  bool operator<=(const ModInt &x) const { return val <= x.val; }
  bool operator>(const ModInt &x) const { return val > x.val; }
  bool operator>=(const ModInt &x) const { return val >= x.val; }
  ModInt &operator++() { if (++val == mod) val = 0; return *this; }
  ModInt operator++(int) { ModInt res = *this; ++*this; return res; }
  ModInt &operator--() { val = (val == 0 ? mod : val) - 1; return *this; }
  ModInt operator--(int) { ModInt res = *this; --*this; return res; }
  ModInt operator+() const { return *this; }
  ModInt operator-() const { return ModInt(val ? mod - val : 0); }
  ModInt operator+(const ModInt &x) const { return ModInt(*this) += x; }
  ModInt operator-(const ModInt &x) const { return ModInt(*this) -= x; }
  ModInt operator*(const ModInt &x) const { return ModInt(*this) *= x; }
  ModInt operator/(const ModInt &x) const { return ModInt(*this) /= x; }
  friend ostream &operator<<(ostream &os, const ModInt &x) { return os << x.val; }
  friend istream &operator>>(istream &is, ModInt &x) { ll val; is >> val; x = ModInt(val); return is; }
};
ModInt abs(const ModInt &x) { return x; }
struct Combinatorics {
  int val; // "val!" and "mod" must be disjoint.
  vector<ModInt> fact, fact_inv, inv;
  Combinatorics(int val = 10000000) : val(val), fact(val + 1), fact_inv(val + 1), inv(val + 1) {
    fact[0] = 1;
    FOR(i, 1, val + 1) fact[i] = fact[i - 1] * i;
    fact_inv[val] = ModInt(1) / fact[val];
    for (int i = val; i > 0; --i) fact_inv[i - 1] = fact_inv[i] * i;
    FOR(i, 1, val + 1) inv[i] = fact[i - 1] * fact_inv[i];
  }
  ModInt nCk(int n, int k) {
    if (n < 0 || n < k || k < 0) return ModInt(0);
    // assert(n <= val && k <= val);
    return fact[n] * fact_inv[k] * fact_inv[n - k];
  }
  ModInt nPk(int n, int k) {
    if (n < 0 || n < k || k < 0) return ModInt(0);
    // assert(n <= val);
    return fact[n] * fact_inv[n - k];
  }
  ModInt nHk(int n, int k) {
    if (n < 0 || k < 0) return ModInt(0);
    return (k == 0 ? ModInt(1) : nCk(n + k - 1, k));
  }
};

int main() {
  const int COL = 2501;
  int r, c; cin >> r >> c;
  int n = r * c;
  BinaryMatrix<COL> m(n, n + 1);
  REP(i, r) REP(j, c) {
    int man; cin >> man;
    m[i * c + j][n] = man;
  }
  REP(i, r) REP(j, c) {
    m[i * c + j][i * c + j] = 1;
    REP(k, 8) {
      for (int y = i + dy8[k], x = j + dx8[k]; 0 <= y && y < r && 0 <= x && x < c; y += dy8[k], x += dx8[k]) {
        m[i * c + j][y * c + x] = 1;
      }
    }
  }
  int rank = gauss_jordan(m, true);
  FOR(row, rank, n) {
    if (m[row][n]) {
      cout << "0\n";
      return 0;
    }
  }
  cout << ModInt(2).pow(n - rank) << '\n';
  return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 3640
final_rank: 3

code_snippet: #define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;
#define FOR(i,m,n) for(int i=(m);i<(n);++i)
#define REP(i,n) FOR(i,0,n)
#define ALL(v) (v).begin(),(v).end()
using ll = long long;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3fLL;
const double EPS = 1e-8;
const int MOD = 1000000007;
// const int MOD = 998244353;
const int dy[] = {1, 0, -1, 0}, dx[] = {0, -1, 0, 1};
const int dy8[] = {1, 1, 0, -1, -1, -1, 0, 1}, dx8[] = {0, -1, -1, -1, 0, 1, 1, 1};
template <typename T, typename U> inline bool chmax(T &a, U b) { return a < b ? (a = b, true) : false; }
template <typename T, typename U> inline bool chmin(T &a, U b) { return a > b ? (a = b, true) : false; }
struct IOSetup {
  IOSetup() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(20);
  }
} iosetup;

template <int COL = 2500>
struct BinaryMatrix {
  int m, n;

  BinaryMatrix(int m, int n = COL, bool def = false) : m(m), n(n), dat(m, bitset<COL>(0)) {
    if (def) {
      REP(i, m) REP(j, n) dat[i][j] = 1;
    }
  }

  BinaryMatrix pow(ll exponent) {
    BinaryMatrix tmp = *this, res(n, n);
    REP(i, n) res[i][i] = 1;
    while (exponent > 0) {
      if (exponent & 1) res *= tmp;
      tmp *= tmp;
      exponent >>= 1;
    }
    return res;
  }

  inline const bitset<COL> &operator[](const int idx) const { return dat[idx]; }
  inline bitset<COL> &operator[](const int idx) { return dat[idx]; }

  BinaryMatrix &operator=(const BinaryMatrix &x) {
    m = x.m;
    n = x.n;
    dat.resize(m);
    REP(i, m) dat[i] = x[i];
    return *this;
  }

  BinaryMatrix &operator+=(const BinaryMatrix &x) {
    REP(i, m) dat[i] ^= x[i];
    return *this;
  }

  BinaryMatrix &operator*=(const BinaryMatrix &x) {
    int height = m, width = x.n;
    BinaryMatrix t_x(x.n, x.m), res(height, width);
    REP(i, x.n) REP(j, x.m) t_x[i][j] = x[j][i];
    REP(i, height) REP(j, width) res[i][j] = ((dat[i] & t_x[j]).count() & 1);
    *this = res;
    return *this;
  }

  BinaryMatrix operator+(const BinaryMatrix &x) const { return BinaryMatrix(*this) += x; }

  BinaryMatrix operator*(const BinaryMatrix &x) const { return BinaryMatrix(*this) *= x; }

private:
  vector<bitset<COL> > dat;
};

template <int COL>
int gauss_jordan(BinaryMatrix<COL> &mat, bool is_extended = false) {
  int rank = 0;
  REP(col, mat.n) {
    if (is_extended && col == mat.n - 1) break;
    int pivot = -1;
    FOR(row, rank, mat.m) {
      if (mat[row][col]) {
        pivot = row;
        break;
      }
    }
    if (pivot == -1) continue;
    swap(mat[rank], mat[pivot]);
    REP(row, mat.m) {
      if (row != rank && mat[row][col]) mat[row] ^= mat[rank];
    }
    ++rank;
  }
  return rank;
}

int mod = MOD;
struct ModInt {
  unsigned val;
  ModInt(): val(0) {}
  ModInt(ll x) : val(x >= 0 ? x % mod : x % mod + mod) {}
  ModInt pow(ll exponent) {
    ModInt tmp = *this, res = 1;
    while (exponent > 0) {
      if (exponent & 1) res *= tmp;
      tmp *= tmp;
      exponent >>= 1;
    }
    return res;
  }
  ModInt &operator+=(const ModInt &x) { if((val += x.val) >= mod) val -= mod; return *this; }
  ModInt &operator-=(const ModInt &x) { if((val += mod - x.val) >= mod) val -= mod; return *this; }
  ModInt &operator*=(const ModInt &x) { val = static_cast<unsigned long long>(val) * x.val % mod; return *this; }
  ModInt &operator/=(const ModInt &x) {
    // assert(__gcd(static_cast<int>(x.val), mod) == 1);
    unsigned a = x.val, b = mod; int u = 1, v = 0;
    while (b) {
      unsigned tmp = a / b;
      swap(a -= tmp * b, b);
      swap(u -= tmp * v, v);
    }
    return *this *= u;
  }
  bool operator==(const ModInt &x) const { return val == x.val; }
  bool operator!=(const ModInt &x) const { return val != x.val; }
  bool operator<(const ModInt &x) const { return val < x.val; }
  bool operator<=(const ModInt &x) const { return val <= x.val; }
  bool operator>(const ModInt &x) const { return val > x.val; }
  bool operator>=(const ModInt &x) const { return val >= x.val; }
  ModInt &operator++() { if (++val == mod) val = 0; return *this; }
  ModInt operator++(int) { ModInt res = *this; ++*this; return res; }
  ModInt &operator--() { val = (val == 0 ? mod : val) - 1; return *this; }
  ModInt operator--(int) { ModInt res = *this; --*this; return res; }
  ModInt operator+() const { return *this; }
  ModInt operator-() const { return ModInt(val ? mod - val : 0); }
  ModInt operator+(const ModInt &x) const { return ModInt(*this) += x; }
  ModInt operator-(const ModInt &x) const { return ModInt(*this) -= x; }
  ModInt operator*(const ModInt &x) const { return ModInt(*this) *= x; }
  ModInt operator/(const ModInt &x) const { return ModInt(*this) /= x; }
  friend ostream &operator<<(ostream &os, const ModInt &x) { return os << x.val; }
  friend istream &operator>>(istream &is, ModInt &x) { ll val; is >> val; x = ModInt(val); return is; }
};
ModInt abs(const ModInt &x) { return x; }
struct Combinatorics {
  int val; // "val!" and "mod" must be disjoint.
  vector<ModInt> fact, fact_inv, inv;
  Combinatorics(int val = 10000000) : val(val), fact(val + 1), fact_inv(val + 1), inv(val + 1) {
    fact[0] = 1;
    FOR(i, 1, val + 1) fact[i] = fact[i - 1] * i;
    fact_inv[val] = ModInt(1) / fact[val];
    for (int i = val; i > 0; --i) fact_inv[i - 1] = fact_inv[i] * i;
    FOR(i, 1, val + 1) inv[i] = fact[i - 1] * fact_inv[i];
  }
  ModInt nCk(int n, int k) {
    if (n < 0 || n < k || k < 0) return ModInt(0);
    // assert(n <= val && k <= val);
    return fact[n] * fact_inv[k] * fact_inv[n - k];
  }
  ModInt nPk(int n, int k) {
    if (n < 0 || n < k || k < 0) return ModInt(0);
    // assert(n <= val);
    return fact[n] * fact_inv[n - k];
  }
  ModInt nHk(int n, int k) {
    if (n < 0 || k < 0) return ModInt(0);
    return (k == 0 ? ModInt(1) : nCk(n + k - 1, k));
  }
};

int main() {
  const int COL = 2501;
  int r, c; cin >> r >> c;
  int n = r * c;
  BinaryMatrix<COL> m(n, n + 1);
  REP(i, r) REP(j, c) {
    int man; cin >> man;
    m[i * c + j][n] = man;
  }
  REP(i, r) REP(j, c) {
    m[i * c + j][i * c + j] = 1;
    REP(k, 8) {
      for (int y = i + dy8[k], x = j + dx8[k]; 0 <= y && y < r && 0 <= x && x < c; y += dy8[k], x += dx8[k]) {
        m[i * c + j][y * c + x] = 1;
      }
    }
  }
  int rank = gauss_jordan(m, true);
  FOR(row, rank, n) {
    if (m[row][n]) {
      cout << "0\n";
      return 0;
    }
  }
  cout << ModInt(2).pow(n - rank) << '\n';
  return 0;
}
accuracy: 0.6615384615384615
time_ms: 50
memory_kb: 3420
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std;

struct Benri { Benri() { std::cin.tie(0); ios::sync_with_stdio(false); cout << fixed << setprecision(12);}} benri;

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using pii = pair<int, int>;
using vll = vector<long long>;
using vvll = vector<vll>;
using pll = pair<ll, ll>;
using ull = unsigned long long;

template <typename T> using PQ = priority_queue<T>;
template <typename T> using minPQ = priority_queue<T, vector<T>, greater<T>>;

#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define mp make_pair
#define F first
#define S second

template<class T>bool chmax(T &a, const T &b) { if (a < b) { a = b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b < a) { a = b; return 1; } return 0; }

//constexpr long long MOD = 1000000007;
//constexpr long long MOD = 998244353;
//constexpr int INF = 1001001001;
constexpr ll INF = 1001001001001001001ll;
constexpr double EPS = 1e-10;
using number = long long;


const int MAX_ROW = 2600; // to be set appropriately
const int MAX_COL = 2600; // to be set appropriately
struct BitMatrix {
    int H, W;
    bitset<MAX_COL> val[MAX_ROW];
    BitMatrix(int m = 1, int n = 1) : H(m), W(n) {}
    inline bitset<MAX_COL>& operator [] (int i) {return val[i];}

    friend ostream& operator << (ostream& os, BitMatrix A) {
        os << endl;
        for (int i = 0; i < A.H; ++i) {
            for (int j = 0; j < A.W; ++j) {
                os << A[i][j] << ", ";
            }
            os << endl;
        }
        return os;
    }
};

int GaussJordan(BitMatrix &A, bool is_extended = false) {
    int rank = 0;
    for (int col = 0; col < A.W; ++col) {
        if (is_extended && col == A.W - 1) break;
        int pivot = -1;
        for (int row = rank; row < A.H; ++row) {
            if (A[row][col]) {
                pivot = row;
                break;
            }
        }
        if (pivot == -1) continue;
        swap(A[pivot], A[rank]);
        for (int row = 0; row < A.H; ++row) {
            if (row != rank && A[row][col]) A[row] ^= A[rank];
        }
        ++rank;
    }
    return rank;
}

int linear_equation(BitMatrix A, vector<int> b, vector<int> &res) {
    int m = A.H, n = A.W;
    BitMatrix M(m, n + 1);
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) M[i][j] = A[i][j];
        M[i][n] = b[i];
    }
    int rank = GaussJordan(M, true);

    // check if it has no solution
    for (int row = rank; row < m; ++row) if (M[row][n]) return -1;

    // answer
    res.assign(n, 0);
    for (int i = 0; i < rank; ++i) res[i] = M[i][n];
    return rank;
};



const int dx[8] = {1, 0, -1, 0, 1, -1, 1, -1};
const int dy[8] = {0, 1, 0, -1, 1, -1, -1, 1};

int R, C;
constexpr long long MOD = 1000000009;

long long modpow(long long a, long long n, long long m) {
    if (n == 0) return 1 % m;
    long long t = modpow(a, n/2, m);
    t = t*t % m;
    if (n & 1) t = t*a % m;
    return t;
}

int main() {
    cin >> R >> C;
    BitMatrix A(R*C, R*C);
    vector<int> b(R*C), res;
    for (int i = 0; i < R; ++i) for (int j = 0; j < C; ++j) cin >> b[i*C + j];
        
    for (int i = 0; i < R; ++i) {
        for (int j = 0; j < C; ++j) {
            int c = i*C + j;
            A[c][c] = 1;
            for (int k = 0; k < 8; ++k) {
                for (int l = 0; l < 50; ++l) {
                    int ni = i + dx[k]*l, nj = j + dy[k]*l;
                    if (ni < 0 || ni >= R || nj < 0 || nj >= C) break;
                    A[ni*C+nj][c] = 1;
                }
            }
        }
    }
         
    int rank = linear_equation(A, b, res);
    if (rank == -1) cout << 0 << endl;
    else cout << modpow(2LL, R*C - rank, MOD) << endl;
}
accuracy: 1
time_ms: 100
memory_kb: 5704
final_rank: 9

code_snippet: #include <iostream>
#include <vector>
#include <bitset>
using namespace std;
typedef long long ll;

// binary行列の掃き出し法と行列累乗
// bitset高速化により、定数倍速い

const int MAX_ROW = 2500;
const int MAX_COL = 2500;
struct BitMatrix {
    int H, W;
    bitset<MAX_COL> val[MAX_ROW];
    BitMatrix(int m, int n) : H(m), W(n) {}
    inline bitset<MAX_COL> & operator [] (int i) { return val[i]; }
};
inline BitMatrix operator * (BitMatrix A, BitMatrix B) {
    BitMatrix R(A.H, B.W);
    BitMatrix tB(B.W, B.H);
    for (int i = 0; i < tB.H; i++) for (int j = 0; j < tB.W; j++) tB[i][j] = B[j][i];
    for (int i = 0; i < R.H; i++) for (int j = 0; j < R.W; j++) R[i][j] = ((A[i] & tB[j]).count() & 1);
    return R;
}
inline BitMatrix pow(BitMatrix A, ll  n) {
    BitMatrix R(A.H, A.H);
    for (int i = 0; i < A.H; ++i) R[i][i] = 1;
    while (n > 0) { if (n & 1) R = R * A; A = A * A; n >>= 1; }
    return R;
}
int GaussJordan(BitMatrix &A, bool is_extended = false) {
    int rank = 0;
    for (int col = 0; col < A.W; col++) {
        if (is_extended && col == A.W - 1) break; // 拡大係数行列。この場合、最後の列は掃き出さない
        int pivot = -1;
        for (int row = rank; row < A.H; row++) if (A[row][col]) { pivot = row; break; }
        if (pivot == -1) continue;
        swap(A[pivot], A[rank]);
        for (int row = 0; row < A.H; row++) if (row != rank && A[row][col]) A[row] ^= A[rank];
        rank++;
    }
    return rank;
}
int linear_equation(BitMatrix A, vector<int> b, vector<int> &res) {
    int m = A.H, n = A.W;
    BitMatrix M(m, n + 1);
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) M[i][j] = A[i][j];
        M[i][n] = b[i];
    }
    int rank = GaussJordan(M, true);
    for (int row = rank; row < m; row++) if (M[row][n]) return -1; // check if it has no solution
    res.assign(n, 0);
    for (int i = 0; i < rank; i++) res[i] = M[i][n];
    return rank;
}

ll pow_mod(ll num, ll pow, ll mod) {
    ll prod = 1;
    num %= mod;
    while (pow > 0) {
        if (pow & 1) prod = prod * num % mod;
        num = num * num % mod;
        pow >>= 1;
    }
    return prod;
}


// verified
//  https://atcoder.jp/contests/code-thanks-festival-2017/tasks/code_thanks_festival_2017_f

// verified
//  https://atcoder.jp/contests/abc141/tasks/abc141_f

// verified
//  https://yukicoder.me/problems/no/184

// verified
//  https://yukicoder.me/problems/no/803

// verified
//  http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1308&lang=en
void AOJ_Awkward_Lights() {
    int m, n, d;
    while (true) {
        cin >> m >> n >> d;
        if (m == 0) break;
        vector <vector<int>> s(n, vector<int>(m));
        for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) cin >> s[i][j];
        BitMatrix A(n * m, n * m);
        vector<int> b(n * m), res;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                A[i * m + j][i * m + j] = 1;
                b[i * m + j] = 1 - s[i][j];
                for (int k = 0; k < n; k++)
                    for (int l = 0; l < m; l++)
                        if (abs(i - k) + abs(j - l) == d) A[i * m + j][k * m + l] = 1;
            }
        }
        cout << (linear_equation(A, b, res) == -1 ? 0 : 1) << '\n';
    }
}


// verified
//  http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2530
void AOJ_Reverse_Game() {
    int r, c;
    cin >> r >> c;
    vector<int> b(r * c), res;
    for (int i = 0; i < r; i++) for (int j = 0; j < c; j++) cin >> b[i * c + j];
    BitMatrix A(r * c, r * c);
    for (int i = 0; i < r; i++)
        for (int j = 0; j < c; j++)
            for (int k = 0; k < r; k++)
                for (int l = 0; l < c; l++)
                    if (i == k || j == l || abs(i - k) == abs(j - l))
                        A[i * c + j][k * c + l] = 1;
    int rank = linear_equation(A, b, res);
    cout << (rank == -1 ? 0 : pow_mod(2, r * c - rank, 1000000009)) << '\n';
}

int main() {
    // AOJ_Awkward_Lights();
    AOJ_Reverse_Game();
    return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 5532
final_rank: 11

code_snippet: #include <iostream>
#include <vector>
#include <bitset>
using namespace std;
typedef long long ll;
const ll MOD = 1000000009LL;

// binary行列の掃き出し法と行列累乗
// bitset高速化により、定数倍速い

const int MAX_ROW = 2500;
const int MAX_COL = 2500;
struct BitMatrix {
    int H, W;
    bitset<MAX_COL> val[MAX_ROW];
    BitMatrix(int m, int n) : H(m), W(n) {}
    inline bitset<MAX_COL> & operator [] (int i) { return val[i]; }
};
inline BitMatrix operator * (BitMatrix A, BitMatrix B) {
    BitMatrix R(A.H, B.W);
    BitMatrix tB(B.W, B.H);
    for (int i = 0; i < tB.H; i++) for (int j = 0; j < tB.W; j++) tB[i][j] = B[j][i];
    for (int i = 0; i < R.H; i++) for (int j = 0; j < R.W; j++) R[i][j] = ((A[i] & tB[j]).count() & 1);
    return R;
}
inline BitMatrix pow(BitMatrix A, ll  n) {
    BitMatrix R(A.H, A.H);
    for (int i = 0; i < A.H; ++i) R[i][i] = 1;
    while (n > 0) { if (n & 1) R = R * A; A = A * A; n >>= 1; }
    return R;
}
int GaussJordan(BitMatrix &A, bool is_extended = false) {
    int rank = 0;
    for (int col = 0; col < A.W; col++) {
        if (is_extended && col == A.W - 1) break; // 拡大係数行列。この場合、最後の列は掃き出さない
        int pivot = -1;
        for (int row = rank; row < A.H; row++) if (A[row][col]) { pivot = row; break; }
        if (pivot == -1) continue;
        swap(A[pivot], A[rank]);
        for (int row = 0; row < A.H; row++) if (row != rank && A[row][col]) A[row] ^= A[rank];
        rank++;
    }
    return rank;
}
int linear_equation(BitMatrix A, vector<int> b, vector<int> &res) {
    int m = A.H, n = A.W;
    BitMatrix M(m, n + 1);
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) M[i][j] = A[i][j];
        M[i][n] = b[i];
    }
    int rank = GaussJordan(M, true);
    for (int row = rank; row < m; row++) if (M[row][n]) return -1; // check if it has no solution
    res.assign(n, 0);
    for (int i = 0; i < rank; i++) res[i] = M[i][n];
    return rank;
}

ll pow_mod(ll num, ll pow, ll mod) {
    ll prod = 1;
    num %= mod;
    while (pow > 0) {
        if (pow & 1) prod = prod * num % mod;
        num = num * num % mod;
        pow >>= 1;
    }
    return prod;
}


// verified
//  https://atcoder.jp/contests/code-thanks-festival-2017/tasks/code_thanks_festival_2017_f

// verified
//  https://atcoder.jp/contests/abc141/tasks/abc141_f

// verified
//  https://yukicoder.me/problems/no/184

// verified
//  https://yukicoder.me/problems/no/803

// verified
//  http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1308&lang=en
void AOJ_Awkward_Lights() {
    int m, n, d;
    while (true) {
        cin >> m >> n >> d;
        if (m == 0) break;
        vector <vector<int>> s(n, vector<int>(m));
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                cin >> s[i][j];
            }
        }
        BitMatrix A(n * m, n * m);
        vector<int> b(n * m), res;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                A[i * m + j][i * m + j] = 1;
                b[i * m + j] = 1 - s[i][j];
                for (int k = 0; k < n; k++) {
                    for (int l = 0; l < m; l++) {
                        if (abs(i - k) + abs(j - l) == d) A[i * m + j][k * m + l] = 1;
                    }
                }
            }
        }
        cout << (linear_equation(A, b, res) == -1 ? 0 : 1) << '\n';
    }
}

void AOJ_Reverse_Game() {
    int r, c;
    cin >> r >> c;
    vector<int> b(r * c), res;
    for (int i = 0; i < r; i++) for (int j = 0; j < c; j++) cin >> b[i * c + j];
    BitMatrix A(r * c, r * c);
    for (int i = 0; i < r; i++) {
        for (int j = 0; j < c; j++) {
            for (int k = 0; k < r; k++) {
                for (int l = 0; l < c; l++) {
                    if (i == k || j == l || abs(i - k) == abs(j - l)) A[i * c + j][k * c + l] = 1;
                }
            }
        }
    }
    int rank = linear_equation(A, b, res);
    cout << (rank == -1 ? 0LL : pow_mod(2LL, r * c - rank, MOD)) << '\n';
}

int main() {
    // AOJ_Awkward_Lights();
    AOJ_Reverse_Game();
    return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 5524
final_rank: 10

code_snippet: #include <iostream>
#include <vector>
#include <bitset>
using namespace std;
typedef long long ll;
const ll MOD = 1000000007LL;

// binary行列の掃き出し法と行列累乗
// bitset高速化により、定数倍速い

const int MAX_ROW = 2500;
const int MAX_COL = 2500;
struct BitMatrix {
    int H, W;
    bitset<MAX_COL> val[MAX_ROW];
    BitMatrix(int m, int n) : H(m), W(n) {}
    inline bitset<MAX_COL> & operator [] (int i) { return val[i]; }
};
inline BitMatrix operator * (BitMatrix A, BitMatrix B) {
    BitMatrix R(A.H, B.W);
    BitMatrix tB(B.W, B.H);
    for (int i = 0; i < tB.H; i++) for (int j = 0; j < tB.W; j++) tB[i][j] = B[j][i];
    for (int i = 0; i < R.H; i++) for (int j = 0; j < R.W; j++) R[i][j] = ((A[i] & tB[j]).count() & 1);
    return R;
}
inline BitMatrix pow(BitMatrix A, ll  n) {
    BitMatrix R(A.H, A.H);
    for (int i = 0; i < A.H; ++i) R[i][i] = 1;
    while (n > 0) { if (n & 1) R = R * A; A = A * A; n >>= 1; }
    return R;
}
int GaussJordan(BitMatrix &A, bool is_extended = false) {
    int rank = 0;
    for (int col = 0; col < A.W; col++) {
        if (is_extended && col == A.W - 1) break; // 拡大係数行列。この場合、最後の列は掃き出さない
        int pivot = -1;
        for (int row = rank; row < A.H; row++) if (A[row][col]) { pivot = row; break; }
        if (pivot == -1) continue;
        swap(A[pivot], A[rank]);
        for (int row = 0; row < A.H; row++) if (row != rank && A[row][col]) A[row] ^= A[rank];
        rank++;
    }
    return rank;
}
int linear_equation(BitMatrix A, vector<int> b, vector<int> &res) {
    int m = A.H, n = A.W;
    BitMatrix M(m, n + 1);
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) M[i][j] = A[i][j];
        M[i][n] = b[i];
    }
    int rank = GaussJordan(M, true);
    for (int row = rank; row < m; row++) if (M[row][n]) return -1; // check if it has no solution
    res.assign(n, 0);
    for (int i = 0; i < rank; i++) res[i] = M[i][n];
    return rank;
}

ll pow_mod(ll num, ll pow, ll mod) {
    ll prod = 1;
    num %= mod;
    while (pow > 0) {
        if (pow & 1) prod = prod * num % mod;
        num = num * num % mod;
        pow >>= 1;
    }
    return prod;
}


// verified
//  https://atcoder.jp/contests/code-thanks-festival-2017/tasks/code_thanks_festival_2017_f

// verified
//  https://atcoder.jp/contests/abc141/tasks/abc141_f

// verified
//  https://yukicoder.me/problems/no/184

// verified
//  https://yukicoder.me/problems/no/803

// verified
//  http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1308&lang=en
void AOJ_Awkward_Lights() {
    int m, n, d;
    while (true) {
        cin >> m >> n >> d;
        if (m == 0) break;
        vector <vector<int>> s(n, vector<int>(m));
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                cin >> s[i][j];
            }
        }
        BitMatrix A(n * m, n * m);
        vector<int> b(n * m), res;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                A[i * m + j][i * m + j] = 1;
                b[i * m + j] = 1 - s[i][j];
                for (int k = 0; k < n; k++) {
                    for (int l = 0; l < m; l++) {
                        if (abs(i - k) + abs(j - l) == d) A[i * m + j][k * m + l] = 1;
                    }
                }
            }
        }
        cout << (linear_equation(A, b, res) == -1 ? 0 : 1) << '\n';
    }
}

void AOJ_Reverse_Game() {
    int r, c;
    cin >> r >> c;
    vector<int> b(r * c), res;
    for (int i = 0; i < r; i++) for (int j = 0; j < c; j++) cin >> b[i * c + j];
    BitMatrix A(r * c, r * c);
    for (int i = 0; i < r; i++) {
        for (int j = 0; j < c; j++) {
            int idx = i * c + j;
            for (int k = 0; k < r; k++) {
                for (int l = 0; l < c; l++) {
                    if (i == k || j == l || abs(i - k) == abs(j - l)) A[idx][k * c + l] = 1;
                }
            }
        }
    }
    int rank = linear_equation(A, b, res);
    cout << (rank == -1 ? 0LL : pow_mod(2LL, r * c - rank, MOD)) << '\n';
}

int main() {
    // AOJ_Awkward_Lights();
    AOJ_Reverse_Game();
    return 0;
}
accuracy: 0.6615384615384615
time_ms: 60
memory_kb: 5512
final_rank: 17

code_snippet: // http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2530
// http://drken1215.hatenablog.com/entry/2019/03/20/164100

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <iostream>
#include <map>
#include <queue>
#include <unordered_map>
#include <vector>
#include <string.h>

using namespace std;

#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl

#define rep(i, n) for(int i = 0; i < n; ++i)
#define all(s) s.begin(), s.end()

typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> P;
typedef tuple<ll, ll, ll> triple;
typedef double D;

int gcd(int a, int b) {
  if (a < b) { swap(a, b); }
  if (b == 0) { return a; }
  return gcd(b, a % b);
}

bool prime(int n) {
  for (int i = 2; i <= sqrt(n); ++i) {
    if (n % i == 0) { return false; }
  }
  return n != 1;
}

template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }

const ll INF = 1e9;
const ll MOD = 1000000009;  // 1e9 + 9

ll powmod(ll x, ll y) {
  ll r = 1;
  while (y) {
    if (y & 1) {
      r = r * x % MOD;
    }
    x = x * x % MOD;
    y >>= 1;
  }
  return r;
}

const int COM_MAX = 500010;
ll fac[COM_MAX], facinv[COM_MAX], inv[COM_MAX];
void COMinit() {
  fac[0] = fac[1] = 1;
  facinv[0] = facinv[1] = 1;
  inv[1] = 1;
  for(int i = 2; i < COM_MAX; ++i) {
    fac[i] = fac[i-1] * i % MOD;
    inv[i] = MOD - inv[MOD%i] * (MOD / i) % MOD;
    facinv[i] = facinv[i-1] * inv[i] % MOD;
  }
}

ll COM(ll n, ll k) {
  return (fac[n] * facinv[k] % MOD) * facinv[n-k] % MOD;
}

ll PERM(ll n, ll k) {
  return (fac[n] * facinv[k] % MOD);
}

const int MAX_ROW = 3010; // To be set appropriately.
const int MAX_COL = 3010; // To be set appropriately.

class BitMatrix {
public:
  BitMatrix(int m = 1, int n = 1) : H(m), W(n) {}
  inline bitset<MAX_COL>& operator [] (int i) { return val[i]; }

  int H, W;

private:
  bitset<MAX_COL> val[MAX_ROW];
};

ostream& operator << (ostream& s, BitMatrix A) {
  s << endl;
  rep(i, A.H) {
    rep(j, A.W) {
      s << A[i][j] << ", ";
    }
    s << endl;
  }
  return s;
}

int GaussJordan(BitMatrix &A, bool is_extended = false) {
  int rank = 0;
  rep(col, A.W) {
    if (is_extended && col == A.W - 1) { break; }
    int pivot = -1;
    for (int row = rank; row < A.H; ++row) {
      if (A[row][col]) {
        pivot = row;
        break;
      }
    }
    if (pivot == -1) continue;
    swap(A[pivot], A[rank]);
    rep(row, A.H) {
      if (row != rank && A[row][col]) {
        A[row] ^= A[rank];
      }
    }
    ++rank;
  }
  return rank;
}

int linear_equation(BitMatrix A, vector<int> b, vector<int> &res) {
  int m = A.H, n = A.W;
  BitMatrix M(m, n + 1);
  rep(i, m) {
    rep(j, n) {
      M[i][j] = A[i][j];
    }
    M[i][n] = b[i];
  }
  int rank = GaussJordan(M, true);

  // check if it has no solution
  for (int row = rank; row < m; ++row) {
    if (M[row][n]) { return -1; }
  }

  // answer
  res.assign(n, 0);
  rep(i, rank) {
    res[i] = M[i][n];
  }
  return rank;
}

const int dx[8] = {1, 0, -1, 0, 1, -1, 1, -1};
const int dy[8] = {0, 1, 0, -1, 1, -1, -1, 1};

int main(int argc, char** argv) {
  int R, C;
  cin >> R >> C;
  BitMatrix A(R*C, R*C);
  vector<int> b(R*C);
  rep(i, R) {
    rep(j, C) {
      cin >> b[i*C + j];
    }
  }

  rep(i, R) {
    rep(j, C) {
      int c = i*C + j;
      A[c][c] = 1;
      rep(k, 8) {
        for (int l = 1; l < 50; ++l) {
          int ni = i + dx[k]*l, nj = j + dy[k]*l;
          if (ni < 0 || ni >= R || nj < 0 || nj >= C) { break; }
          A[ni*C+nj][c] = 1;
        }
      }
    }
  }

  vector<int> res;
  int rank = linear_equation(A, b, res);
  // COUT(rank);
  if (rank == -1) {
    cout << 0 << endl;
  } else {
    cout << powmod(2LL, R*C - rank) << endl;
  }
}
accuracy: 1
time_ms: 110
memory_kb: 6564
final_rank: 13

code_snippet: #include <algorithm>
#include <iostream>
#include <vector>
#include <bitset>
using namespace std;

const int MAX_ROW = 2600; // to be set appropriately
const int MAX_COL = 2600; // to be set appropriately
struct BitMatrix {
    int H, W;
    bitset<MAX_COL> val[MAX_ROW];
    BitMatrix(int m = 1, int n = 1) : H(m), W(n) { }
    bitset<MAX_COL>& operator[] (int i) { return val[i]; }
};
int GaussJordan(BitMatrix &A, bool is_extended = false) {
    int rank = 0;
    for (int col = 0; col < A.W; ++col) {
        if (is_extended && col == A.W - 1) break;
        int pivot = -1;
        for (int row = rank; row < A.H; ++row) {
            if (A[row][col]) { pivot = row; break; }
        }
        if (pivot == -1) continue;
        swap(A[pivot], A[rank]);
        for (int row = 0; row < A.H; ++row) {
            if (row != rank && A[row][col]) A[row] ^= A[rank];
        }
        ++rank;
    }
    return rank;
}
int linear_equation(BitMatrix A, vector<int> b, vector<int> &res) {
    int m = A.H, n = A.W;
    BitMatrix M(m, n + 1);          // augmented matrix (A|B)
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) M[i][j] = A[i][j];
        M[i][n] = b[i];
    }
    int rank = GaussJordan(M, true);
    // check if it has no solution
    for (int row = rank; row < m; ++row) if (M[row][n]) return -1;
    // answer
    res.assign(n, 0);
    for (int i = 0; i < rank; ++i) res[i] = M[i][n];
    return rank;
};

long long modpow(long long a, long long n, long long mod) {
	long long res = 1;
	while (n) {
		if (n & 1) (res *= a) %= mod;
		(a *= a) %= mod;
		n >>= 1;
	}
	return res;
}

const int dx[8] = {1, 0, -1, 0, 1, -1, 1, -1};
const int dy[8] = {0, 1, 0, -1, 1, -1, -1, 1};

int main() {
    int r, c; cin >> r >> c;
    BitMatrix A(r * c, r * c);
    vector<int> b(r * c), res;
    for (int i = 0; i < r; i++) {
        for (int j = 0; j < c; j++) cin >> b[i*c + j];
    }
    for (int i = 0; i < r; i++) {
        for (int j = 0; j < c; j++) {
            int cur = i*c + j;
            A[cur][cur] = 1;
            for (int k = 0; k < 8; k++) {
                for (int l = 1; l < 50; l++) {
                    int ni = i + dx[k]*l, nj = j + dy[k]*l;
                    if (ni < 0 || ni >= r || nj < 0 || nj >= c) break;
                    A[ni*c + nj][cur] = 1;
                }
            }
        }
    }
    int rank = linear_equation(A, b, res);
    if (rank == -1) cout << 0 << endl;
    else cout << modpow(2LL, r*c - rank, (int)1e9 + 9) << endl;
    return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 5680
final_rank: 7

code_snippet: #include <algorithm>
#include <iostream>
#include <vector>
#include <bitset>
using namespace std;

const int MAX_ROW = 2500; // to be set appropriately
const int MAX_COL = 2500; // to be set appropriately
struct BitMatrix {
    int H, W;
    bitset<MAX_COL> val[MAX_ROW];
    BitMatrix(int m = 1, int n = 1) : H(m), W(n) { }
    bitset<MAX_COL>& operator[] (int i) { return val[i]; }
};
int GaussJordan(BitMatrix &A, bool is_extended = false) {
    int rank = 0;
    for (int col = 0; col < A.W; ++col) {
        if (is_extended && col == A.W - 1) break;
        int pivot = -1;
        for (int row = rank; row < A.H; ++row) {
            if (A[row][col]) { pivot = row; break; }
        }
        if (pivot == -1) continue;
        swap(A[pivot], A[rank]);
        for (int row = 0; row < A.H; ++row) {
            if (row != rank && A[row][col]) A[row] ^= A[rank];
        }
        ++rank;
    }
    return rank;
}
int linear_equation(BitMatrix A, vector<int> b, vector<int> &res) {
    int m = A.H, n = A.W;
    BitMatrix M(m, n + 1);          // augmented matrix (A|B)
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) M[i][j] = A[i][j];
        M[i][n] = b[i];
    }
    int rank = GaussJordan(M, true);
    // check if it has no solution
    for (int row = rank; row < m; ++row) if (M[row][n]) return -1;
    // answer
    res.assign(n, 0);
    for (int i = 0; i < rank; ++i) res[i] = M[i][n];
    return rank;
};

long long modpow(long long a, long long n, long long mod) {
	long long res = 1;
	while (n) {
		if (n & 1) (res *= a) %= mod;
		(a *= a) %= mod;
		n >>= 1;
	}
	return res;
}

const int dx[8] = {1, 0, -1, 0, 1, -1, 1, -1};
const int dy[8] = {0, 1, 0, -1, 1, -1, -1, 1};

int main() {
    int r, c; cin >> r >> c;
    BitMatrix A(r * c, r * c);
    vector<int> b(r * c), res;
    for (int i = 0; i < r; i++) {
        for (int j = 0; j < c; j++) cin >> b[i*c + j];
    }
    for (int i = 0; i < r; i++) {
        for (int j = 0; j < c; j++) {
            int cur = i*c + j;
            A[cur][cur] = 1;
            for (int k = 0; k < 8; k++) {
                for (int l = 0; l < 50; l++) {
                    int ni = i + dx[k]*l, nj = j + dy[k]*l;
                    if (ni < 0 || ni >= r || nj < 0 || nj >= c) break;
                    A[cur][ni*c + nj] = 1;
                }
            }
        }
    }
    int rank = linear_equation(A, b, res);
    if (rank == -1) cout << 0 << endl;
    else cout << modpow(2LL, r*c - rank, (int)1e9 + 7) << endl;
    return 0;
}
accuracy: 0.6615384615384615
time_ms: 60
memory_kb: 5516
final_rank: 18

code_snippet: #include <algorithm>
#include <iostream>
#include <vector>
#include <bitset>
using namespace std;

const int MAX_ROW = 2500; // to be set appropriately
const int MAX_COL = 2500; // to be set appropriately
struct BitMatrix {
    int H, W;
    bitset<MAX_COL> val[MAX_ROW];
    BitMatrix(int m = 1, int n = 1) : H(m), W(n) { }
    bitset<MAX_COL>& operator[] (int i) { return val[i]; }
};
int GaussJordan(BitMatrix &A, bool is_extended = false) {
    int rank = 0;
    for (int col = 0; col < A.W; ++col) {
        if (is_extended && col == A.W - 1) break;
        int pivot = -1;
        for (int row = rank; row < A.H; ++row) {
            if (A[row][col]) { pivot = row; break; }
        }
        if (pivot == -1) continue;
        swap(A[pivot], A[rank]);
        for (int row = 0; row < A.H; ++row) {
            if (row != rank && A[row][col]) A[row] ^= A[rank];
        }
        ++rank;
    }
    return rank;
}
int linear_equation(BitMatrix A, vector<int> b, vector<int> &res) {
    int m = A.H, n = A.W;
    BitMatrix M(m, n + 1);          // augmented matrix (A|B)
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) M[i][j] = A[i][j];
        M[i][n] = b[i];
    }
    int rank = GaussJordan(M, true);
    // check if it has no solution
    for (int row = rank; row < m; ++row) if (M[row][n]) return -1;
    // answer
    res.assign(n, 0);
    for (int i = 0; i < rank; ++i) res[i] = M[i][n];
    return rank;
};

long long modpow(long long a, long long n, long long mod) {
	long long res = 1;
	while (n) {
		if (n & 1) (res *= a) %= mod;
		(a *= a) %= mod;
		n >>= 1;
	}
	return res;
}

const int dx[8] = {1, 0, -1, 0, 1, -1, 1, -1};
const int dy[8] = {0, 1, 0, -1, 1, -1, -1, 1};

int main() {
    int r, c; cin >> r >> c;
    BitMatrix A(r * c, r * c);
    vector<int> b(r * c), res;
    for (int i = 0; i < r; i++) {
        for (int j = 0; j < c; j++) cin >> b[i*c + j];
    }
    for (int i = 0; i < r; i++) {
        for (int j = 0; j < c; j++) {
            int cur = i*c + j;
            A[cur][cur] = 1;
            for (int k = 0; k < 8; k++) {
                for (int l = 0; l < 50; l++) {
                    int ni = i + dx[k]*l, nj = j + dy[k]*l;
                    if (ni < 0 || ni >= r || nj < 0 || nj >= c) break;
                    A[ni*c + nj][cur] = 1;
                }
            }
        }
    }
    int rank = linear_equation(A, b, res);
    if (rank == -1) cout << 0 << endl;
    else cout << modpow(2LL, r*c - rank, (int)1e9 + 7) << endl;
    return 0;
}
accuracy: 0.6615384615384615
time_ms: 50
memory_kb: 5520
final_rank: 16