結果
| 問題 |
No.226 0-1パズル
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2020-11-11 00:12:51 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 20 ms / 5,000 ms |
| コード長 | 3,678 bytes |
| コンパイル時間 | 2,249 ms |
| コンパイル使用メモリ | 206,108 KB |
| 最終ジャッジ日時 | 2025-01-15 22:03:47 |
|
ジャッジサーバーID (参考情報) |
judge3 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 22 |
ソースコード
#include <bits/stdc++.h>
#include <cassert>
#define rep(i, n) for (int i = 0; i < (n); i++)
using namespace std;
using ll = long long;
using P = pair<int, int>;
/*
struct Edge
{
int to;
int weight;
Edge(int t, int w) : to(t), weight(w) {}
};
using Graph = vector<vector<Edge>>;
*/
using Graph = vector<vector<int>>;
const long long INF = 1LL << 60;
const int INT_INF = 1000000000;
int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
// int dx[8] = {-1, -1, -1, 0, 0, 1, 1, 1}, dy[8] = {-1, 0, 1, 1, -1, 1, 0, -1};
const int mod = 1000000007;
struct mint
{
ll x; // typedef long long ll;
mint(ll x = 0) : x((x % mod + mod) % mod) {}
mint operator-() const { return mint(-x); }
mint &operator+=(const mint a)
{
if ((x += a.x) >= mod)
x -= mod;
return *this;
}
mint &operator-=(const mint a)
{
if ((x += mod - a.x) >= mod)
x -= mod;
return *this;
}
mint &operator*=(const mint a)
{
(x *= a.x) %= mod;
return *this;
}
mint operator+(const mint a) const { return mint(*this) += a; }
mint operator-(const mint a) const { return mint(*this) -= a; }
mint operator*(const mint a) const { return mint(*this) *= a; }
mint pow(ll t) const
{
if (!t)
return 1;
mint a = pow(t >> 1);
a *= a;
if (t & 1)
a *= *this;
return a;
}
// for prime mod
mint inv() const { return pow(mod - 2); }
mint &operator/=(const mint a) { return *this *= a.inv(); }
mint operator/(const mint a) const { return mint(*this) /= a; }
};
istream &operator>>(istream &is, const mint &a) { return is >> a.x; }
ostream &operator<<(ostream &os, const mint &a) { return os << a.x; }
struct combination
{
vector<mint> fact, ifact;
combination(int n) : fact(n + 1), ifact(n + 1)
{
assert(n < mod);
fact[0] = 1;
for (int i = 1; i <= n; ++i)
fact[i] = fact[i - 1] * i;
ifact[n] = fact[n].inv();
for (int i = n; i >= 1; --i)
ifact[i - 1] = ifact[i] * i;
}
mint operator()(int n, int k)
{
if (k < 0 || k > n)
return 0;
return fact[n] * ifact[k] * ifact[n - k];
}
mint p(int n, int k)
{
return fact[n] * ifact[n - k];
}
} c(1000005);
// 左上をvalとした市松模様がvalidかどうか
bool isValid(const vector<string> &S, int val)
{
for (int i = 0; i < S.size(); i++)
{
for (int j = 0; j < S[0].size(); j++)
{
if (S[i][j] == '0' && (i + j + val) % 2 == 1)
return false;
if (S[i][j] == '1' && (i + j + val) % 2 == 0)
return false;
}
}
return true;
}
// 最初の行としてありうるものの個数
mint solve(const vector<string> &S)
{
int power = 0;
for (int j = 0; j < S[0].size(); j++)
{
set<int> st;
for (int i = 0; i < S.size(); i++)
{
if (S[i][j] == '0')
{
if (i % 2 == 0)
st.insert(0);
else
st.insert(1);
}
else if (S[i][j] == '1')
{
if (i % 2 == 0)
st.insert(1);
else
st.insert(0);
}
}
if (st.size() == 2)
return mint(0);
if (st.size() == 0)
power++;
}
return mint(2).pow(power);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int H, W;
cin >> H >> W;
vector<string> S(H);
for (auto &it : S)
cin >> it;
mint res = solve(S);
vector<string> se(W, string(H, '?'));
for (int j = 0; j < W; j++)
{
for (int i = 0; i < H; i++)
{
se[j][i] = S[i][j];
}
}
res += solve(se);
mint sub = 0;
if (isValid(S, 0))
sub += 1;
if (isValid(S, 1))
sub += 1;
res -= sub;
cout << res << endl;
return 0;
}
// https://yukicoder.me/problems/no/226/editorial