結果
問題 | No.1397 Analog Graffiti |
ユーザー |
![]() |
提出日時 | 2021-02-14 20:18:56 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
TLE
(最新)
AC
(最初)
|
実行時間 | - |
コード長 | 4,354 bytes |
コンパイル時間 | 1,312 ms |
コンパイル使用メモリ | 104,808 KB |
最終ジャッジ日時 | 2025-01-18 20:28:21 |
ジャッジサーバーID (参考情報) |
judge5 / judge5 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 TLE * 1 |
other | AC * 23 TLE * 1 |
ソースコード
#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 0const 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){// encodeKey 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];// decodeauto 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);}//すでに黒い部分があった後、再度黒い部分があるのは NGif(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;}//unifyif(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++;}// renumbervi 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);}// encodeKey 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;//一段多く。最後は 0rep(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;}