TopCoder SRM 550 Div1 Medium CheckerExpansion
問題
無限に広いチェス盤がある。最初どのマスにも駒は置かれていない。
左上を(0, 0)とする。以下t回以下の操作を繰り返す。
- 1回目は(0, 0)にAを置く
- 次からはB, Aと交互に置く
- (x - 2, y)と(x - 1, y - 1)の2マスのうち、どちらか一方のみに今置こうとしている駒でない駒があった場合、(x, y)に駒を置く
操作を繰り返した後のチェス盤の、
(x0, y0)から幅w高さhの部分を出力せよ。
制約条件
t≦10^12
x0, y0≦10^12
h, w≦50
方針
A.B.A.B.A.B.A.B.A.B.A.B.A.B.A. .B...B...B...B...B...B...B...B ..A.B.....A.B.....A.B.....A.B. ...B.......B.......B.......B.. ....A.B.A.B.........A.B.A.B... .....B...B...........B...B.... ......A.B.............A.B..... .......B...............B...... ........A.B.A.B.A.B.A.B....... .........B...B...B...B........ ..........A.B.....A.B......... ...........B.......B.......... ............A.B.A.B........... .............B...B............ ..............A.B............. ...............B.............. ................A.B.A.B.A..... .................B...B........ ..................A.B......... ...................B..........
実験してみると、上のように駒が置かれることがわかる。
t回後には、x + y == 2 * tの駒が置かれるので、x + y≦2*tの部分だけ、
どの駒があるかを考えればよい。
ソースコード
char calc(ll y, ll x){ if(x < y) return '.'; ll h = 2, w = 4, level = 1; while(y >= h || x >= w){ h *= 2; w *= 2; level++; } while(level > 1){ h /= 2; w /= 2; level--; if(y < h) x = x % w; else{ y -= h; x -= h; } if(x >= h && x + y > w - 2) return '.'; if(x < h && x < y) return '.'; } if(y == 0) return "A.B."[x]; return ".B.."[x]; } class CheckerExpansion { public: vector <string> resultAfter(long long t, long long x0, long long y0, int w, int h) { vector<string> ans(h, string(w, '.')); rep(i, h) rep(j, w){ if(y0 + i + x0 + j < 2 * t) ans[h - 1 - i][j] = calc(y0 + i, x0 + j); } return ans; } };