結果
問題 | No.1397 Analog Graffiti |
ユーザー | 夕叢霧香(ゆうむらきりか) |
提出日時 | 2021-02-14 20:18:56 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 9,491 ms / 10,000 ms |
コード長 | 4,354 bytes |
コンパイル時間 | 1,614 ms |
コンパイル使用メモリ | 111,628 KB |
実行使用メモリ | 132,736 KB |
最終ジャッジ日時 | 2024-07-26 18:20:58 |
合計ジャッジ時間 | 82,062 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
6,816 KB |
testcase_01 | AC | 2 ms
6,940 KB |
testcase_02 | AC | 9,393 ms
132,736 KB |
testcase_03 | AC | 2 ms
6,940 KB |
testcase_04 | AC | 2 ms
6,944 KB |
testcase_05 | AC | 9,482 ms
132,736 KB |
testcase_06 | AC | 2 ms
6,944 KB |
testcase_07 | AC | 8 ms
6,944 KB |
testcase_08 | AC | 7 ms
6,940 KB |
testcase_09 | AC | 3 ms
6,940 KB |
testcase_10 | AC | 2 ms
6,940 KB |
testcase_11 | AC | 9,139 ms
130,048 KB |
testcase_12 | AC | 1,248 ms
23,808 KB |
testcase_13 | AC | 8,622 ms
127,488 KB |
testcase_14 | AC | 9,413 ms
132,736 KB |
testcase_15 | AC | 9,491 ms
132,736 KB |
testcase_16 | AC | 1,213 ms
23,424 KB |
testcase_17 | AC | 9,011 ms
130,176 KB |
testcase_18 | AC | 8,788 ms
127,488 KB |
testcase_19 | AC | 5 ms
6,940 KB |
testcase_20 | AC | 7 ms
6,940 KB |
testcase_21 | AC | 86 ms
6,940 KB |
testcase_22 | AC | 2,777 ms
67,456 KB |
testcase_23 | AC | 182 ms
12,032 KB |
testcase_24 | AC | 3 ms
6,944 KB |
testcase_25 | AC | 409 ms
20,352 KB |
testcase_26 | AC | 3 ms
6,940 KB |
ソースコード
#include<algorithm> #include<cassert> #include<iostream> #include<map> #include<set> #include<vector> using namespace std; typedef long long lint; typedef vector<int>vi; typedef pair<int,int>pii; #define rep(i,n)for(int i=0;i<(int)(n);++i) //参考 https://atcoder.jp/contests/tdpc/submissions/3921962 #define PRINT 0 const lint mo=998244353; const int LIM = 6; const int LOG_BASE = 4; int W,N; using Key=lint; map<Key,Key>cache[1<<LIM]; // 0 から W-1 黒 // W から 2W-1 白 pair<vi,int>tovi(Key key){ vi a(W); rep(z,W){ a[z] = (int)((key >> (z * LOG_BASE)) & ((1 << LOG_BASE) - 1)); } int b=key>>(LOG_BASE*W); return make_pair(a,b); } Key tokey(vi a,int b){ // encode Key keyNext=0; assert(a.size()==W); rep(z,W){ assert(a[z]<2*W); keyNext |= (Key)(a[z]) << (z * LOG_BASE); } return keyNext|lint(b)<<(LOG_BASE*W); } void unify(vi&a,int x,int y){ int oldx=a[x],oldy=a[y]; assert(oldx/(2*W)==oldy/(2*W)); int to=min(oldx,oldy); rep(i,a.size())if(a[i]==oldx||a[i]==oldy)a[i]=to; } Key trans(Key key,int pat) { if(cache[pat].count(key))return cache[pat][key]; // decode auto ab = tovi(key); vi a; int b; tie(a,b)=ab; vi chu(2*W); int bl=0,wh=2*W+1; rep(i,W){ chu[i]=a[i]<W?a[i]:a[i]+W; if(a[i]<W)bl=max(bl,a[i]+1); else wh=max(wh,W+a[i]+1); } //すでに黒い部分があった後、再度黒い部分があるのは NG if(b>0&&bl==0&&pat>0)return cache[pat][key]=-1; rep(i,W)chu[i+W]=(pat&1<<i)?bl++:min(4*W-1,wh++); if(PRINT&&pat==3){ cerr<<"a="; rep(i,a.size())cerr<<" "<<a[i]; cerr<<" b="<<b; cerr<<" "<<pat<<endl; rep(i,2*W)cerr<<" "<<chu[i]; cerr<<endl; } //unify if(chu[W]>=2*W)chu[W]=2*W; if(chu[2*W-1]>=2*W)chu[2*W-1]=2*W; rep(j,2)rep(i,W-1)if(chu[j*W+i]/(2*W)==chu[j*W+i+1]/(2*W))unify(chu,j*W+i,j*W+i+1); rep(i,W)if(chu[i]/(2*W)==chu[i+W]/(2*W))unify(chu,i,i+W); //繋がらないことが確定した白がある? set<int>top; rep(i,W)if(chu[i+W]>2*W)top.insert(chu[i+W]); rep(i,W)if(chu[i]>2*W&&!top.count(chu[i]))return cache[pat][key]=-1; //繋がらないことが確定した黒がある? top.clear(); set<int>lft; rep(i,W)if(chu[i+W]<2*W)top.insert(chu[i+W]); rep(i,W)if(chu[i]<2*W&&!top.count(chu[i]))lft.insert(chu[i]); if(pat>0&&lft.size())return cache[pat][key]=-1; if(pat==0&&lft.size()>1)return cache[pat][key]=-1; //新しい頂点の個数は? rep(i,W+1){ int c=0; rep(j,2)rep(k,2)c+=(i-k>=0&&i-k<W?chu[j*W+i-k]<2*W:0); if(c%2)b++; } // renumber vi c(chu.begin()+W,chu.end()); bl=0,wh=W+1; int tr[4*LIM]={}; rep(i,4*LIM)tr[i]=-1; tr[2*W]=W; rep(z,W){ if (tr[c[z]] == -1) { tr[c[z]] = c[z]>=2*W?wh++:bl++; } } assert(tr[2*W]==-1||tr[2*W]==W); rep(z,W){ c[z] = tr[c[z]]; assert(c[z]<2*W); } // encode Key keyNext=tokey(c,b); cache[pat][key]=keyNext; return keyNext; } int main(){ int r,c,n;cin>>r>>c>>n; W=c;N=n; lint ans=0; map<Key,lint>crt; vi fst(W); rep(i,W){ fst[i]=W; } crt[tokey(fst,0)]=1; //一段多く。最後は 0 rep(i,r+1){ cerr<<"i="<<i<<" |crt|="<<crt.size()<<endl; if(PRINT){ cerr<<endl; cerr<<"i="<<i<<endl; } map<Key,lint>nxt; for(auto t:crt){ Key key;lint val; tie(key,val)=t; auto ab=tovi(key); vi a; int b; tie(a,b)=ab; rep(pat,1<<W){ Key to=trans(key,pat); if(to<0){ if(PRINT){ cerr<<"a="; rep(i,a.size())cerr<<" "<<a[i]; cerr<<" b="<<b<<" val="<<val; cerr<<" pat="<<pat<<" INVALID"<<endl; } continue; } if(PRINT){ cerr<<"a="; rep(i,a.size())cerr<<" "<<a[i]; cerr<<" b="<<b<<" val="<<val; vi c; int d; tie(c,d)=tovi(to); cerr<<" to="; rep(i,c.size())cerr<<" "<<c[i]; cerr<<" bafter="<<d<<endl; } (nxt[to]+=val)%=mo; } } crt=nxt; } for(auto t:crt){ Key key;lint val; tie(key,val)=t; auto ab=tovi(key); vi a; int b; tie(a,b)=ab; if(PRINT){ cerr<<"a="; rep(i,a.size())cerr<<" "<<a[i]; cerr<<" b="<<b<<" val="<<val<<endl; } if(a!=fst||b!=N)continue; (ans+=val)%=mo; } cout<<ans<<endl; }