結果
問題 | No.2837 Flip Triomino |
ユーザー |
![]() |
提出日時 | 2024-08-09 22:48:30 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 110 ms / 2,000 ms |
コード長 | 4,319 bytes |
コンパイル時間 | 2,283 ms |
コンパイル使用メモリ | 201,668 KB |
最終ジャッジ日時 | 2025-02-23 21:58:20 |
ジャッジサーバーID (参考情報) |
judge4 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 34 |
ソースコード
//#pragma GCC target("avx2")//#pragma GCC optimize("O3")//#pragma GCC optimize("unroll-loops")#include <bits/stdc++.h>using namespace std;using ll = long long;using pii = pair<int,int>;using pll = pair<ll,ll>;using pli = pair<ll,int>;#define TEST cerr << "TEST" << endl#define AMARI 998244353//#define AMARI 1000000007#define el '\n'#define El '\n'#define int ll// 二項係数の計算(余り付き)// nCkについて、n,k<10^7の時前処理O(N)、計算O(1)で行うclass ococo_combination {public:long long n, p;vector<long long> kaizyou, gyakugen, gyakugen_kaizyou;// 二項係数に出てくる最大値をaに変更する// O(1) ここで変更したaが他の関数の計算時間に影響を与える。void update_max(int a) {n = a;kaizyou.resize(n);gyakugen.resize(n);gyakugen_kaizyou.resize(n);}// 素数で割った余りを出力する時その余りをpに変更する// a = 0にすると余りは出さずに計算する// O(1)void update_mod(int a) {p = a;}// 前処理を行う update_maxとupdate_modを先にやった方が良い// O(N)void maesyori(void) {kaizyou[0] = 1;gyakugen[0] = 1;gyakugen_kaizyou[0] = 1;kaizyou[1] = 1;gyakugen[1] = 1;gyakugen_kaizyou[1] = 1;for(int i = 2; i < n; i++) {kaizyou[i] = kaizyou[i - 1] * i % p;gyakugen[i] = p - gyakugen[p % i] * (p / i) % p;gyakugen_kaizyou[i] = gyakugen_kaizyou[i - 1] * gyakugen[i] % p;}}// 二項係数nCkの計算を行う// O(1)long long nCk(int n, int k) {if(n < k || n < 0 || k < 0) return 0;else {long long ans = kaizyou[n];long long kari = gyakugen_kaizyou[n - k];kari %= p;kari *= gyakugen_kaizyou[k];kari %= p;ans *= kari;ans %= p;return ans;}}};#define MULTI_TEST_CASE falsevoid solve(void){//問題を見たらまず「この問題設定から言えること」をいっぱい言う//一個回答に繋がりそうな解法が見えても、実装や細かい詰めに時間がかかりそうなら別の方針を考えてみる//添え字回りで面倒になりそうなときは楽になる言い換えを実装の前にじっくり考える//ある程度考察しても全然取っ掛かりが見えないときは実験をしてみる//よりシンプルな問題に言い換えられたら、言い換えた先の問題を自然言語ではっきりと書くint h,w;cin >> h >> w;vector<string> s(h);for(int i = 0; i < h; i++)cin >> s[i];vector<int> bl(3,0),wh(3,0),qu(3,0);for(int i = 0; i < h; i++){for(int j = 0; j < w; j++){if(s[i][j] == 'B')bl[(i + j + 3 * h + 3 * w) % 3]++;if(s[i][j] == 'W')wh[(i + j + 3 * h + 3 * w) % 3]++;if(s[i][j] == '?')qu[(i + j + 3 * h + 3 * w) % 3]++;}}//bl[0],bl[1],bl[2] それぞれについて、全部偶奇が揃ってなければいけないll ans = 0;ococo_combination cb;cb.update_max(2500000);cb.update_mod(AMARI);cb.maesyori();vector<ll> cnt_even(3),cnt_odd(3);for(int j = 0; j < 3; j++)for(int i = 0; i <= qu[j]; i++){if((i + bl[j]) % 2)cnt_odd[j] += cb.nCk(qu[j],i);else cnt_even[j] += cb.nCk(qu[j],i);cnt_odd[j] %= AMARI;cnt_even[j] %= AMARI;//cerr << cnt_odd[j] << ' ' << cnt_even[j] << el;}//全部偶数ll temp = 1;for(int i = 0; i < 3; i++){//cerr << cnt_even[i] << ' ';temp *= cnt_even[i]; temp %= AMARI;}//cerr << el;ans += temp;//全部奇数temp = 1;for(int i = 0; i < 3; i++){//cerr << cnt_odd[i] << ' ';temp *= cnt_odd[i]; temp %= AMARI;}//cerr << el;ans += temp;ans %= AMARI;cout << ans << el;return;}void calc(void){return;}signed main(void){cin.tie(nullptr);ios::sync_with_stdio(false);calc();int t = 1;if(MULTI_TEST_CASE)cin >> t;while(t--){solve();}return 0;}