方針を思いついても、短く書くの難しいな。
https://yukicoder.me/problems/no/2631
問題
H*Wのグリッドが与えられ、2人でゲームを行う。
初期状態でそれぞれ1つのマスの駒を行う。
以後、各人のターンでは以下の動作を行う。
- 駒を移動する。ただし、自分が占拠済みの矩形と、移動先のマスを包含する最小の矩形が、相手が占拠済みの矩形と重なってはならない。
- 駒を移動後、自分が占拠済みの矩形と、移動先のマスを包含する最小の矩形を占拠した状態となる。
最終的により多くの領域を占拠した方が勝利となる。
2つの駒の初期配置のうち、先手が必勝となるのは何通りか。
解法
先手の駒を矩形の左上1/4に配置したとき、先手が負ける後手の駒の配置を考える。
これはだいたい先手の駒と、グリッドの中心を含む矩形領域である(厳密には右や下に1はみ出すこともある)
よってこれらを数え上げればよい。
ll H,W; const ll mo=998244353; ll hoge(ll X,ll Y) { ll A=H/2+2; ll B=W/2+2; ll ret=0; ret+=(H*W-A*B)%mo*X%mo*Y%mo; ret+=B*(X*(X+1)/2%mo)%mo*Y%mo; ret+=A*(Y*(Y+1)/2%mo)%mo*X%mo; ret-=(X*(X+1)/2%mo)*(Y*(Y+1)/2%mo)%mo; return (ret%mo+mo)%mo; }; void solve() { int i,j,k,l,r,x,y; string s; cin>>H>>W; ll ret=0; ret+=hoge(H/2,W/2); ret+=hoge((H+1)/2,W/2); ret+=hoge(H/2,(W+1)/2); ret+=hoge((H+1)/2,(W+1)/2); cout<<ret%mo<<endl; }
まとめ
1数え間違えそうな箇所が多くて怖い。