AGC066-B 解法

自分のコンテスト中の解法

 N=4 の場合を考える.次のような数を考える: 5^0, 5^1, 5^2,5^3,5^4 を並べる.ただし,お互いが干渉しないように適宜間に  0 を追加する.

ここでは,間に  0 10 個追加して  x=10000000000500000000002500000000001250000000000625 とする.

このとき,  x,2x,4x,8x,16x は次のような振る舞いをする.

 10000000000500000000002500000000001250000000000625
 20000000001000000000005000000000002500000000001250
 40000000002000000000010000000000005000000000002500
 80000000004000000000020000000000010000000000005000
160000000008000000000040000000000020000000000010000

例えば  x から  2x への変化に注目すると,  x から 625 を削除して,新たに  2 を追加したものとみることができる.同様に,  2^{i-1} x から  2^{i}x への変化は  5^{5-i} を削除して新たに  2^{i} を追加したものとしてみることができる.したがって, 5^{5-i} の桁和が  2^{i} の桁和より大きくなっていればよい.

このままでは不十分だが,次のように問題を一般化してみる:

 5^{0}, 5^{1}, \ldots, 5^{M-1} の間に適宜  0 を追加した数を考える.このとき,各  i=1,2,\ldots,N に対して  5^{M-i} の桁和が  2^{i} の桁和より大きくなっているか?

これを厳密に紙面上で判定するのは難しいが, 2^{i} がそこまで大きくない(せいぜい  10^{15} ぐらい)ため, 2^{i} の桁和も雑に見積もっても  15\cdot 9 にしかなりえない.よって,  M を比較的大きめにとることで  5^{M-i} の桁数が増え,結果的に  5^{M-i} の桁和を  2^i の桁和よりも大きくすることが(期待)できる.

実際に,例えば  M=100 ,間の  0 の個数を  20 個(これで十分干渉しない)にすることで AC が得られた.

TUPC2023 開催記

TUPC2023 を開催しました.

atcoder.jp

準備記録とか運営記録とかは他の運営の子たちが書いてくれてるのでさぼってそちらに譲ります.各問題について感想など.

A - Namboku / Tozai Line

Welcome 枠.

B - 012 Grid

LGV 公式を知らず解説 AC.結構面倒だと思って取り掛かったらシンプルになって感動.ABC 上位勢たちがたくさん通してくると予想してたがハズレ.

C - Topological Sort

Writer.設定がシンプルで考察もちょっとあってそこそこ面白枠だったんじゃないかなと.サンプルで人々をだまそうと思って答えが 2 べきになるケースしか置かなかったらみんなだまされててにこにこしてた.線形で解けるのが地味に推しポイント.

D - Shift Puzzle

Writer.去年 7 月の AGC063 で大敗した後に嫌になって作問してたら思いついた問題.3 点 rotate を利用して 2 点 swap が実現できるのがびっくり. N^3 回っていう制約が想定解だとちょうどぴったりになる.FA の zkou さんが想定で解いてくれたらしくうれしい.非想定解法もいくつかあるみたい.

E - And DNA

自分は実験・実験・OEIS で解いてしまったのでこの問題は面白ポイントがまだわかっていないが,ちゃんと解くと面白ポイントがあるらしく評判は良かったみたい.問題名の DNA が何なのかずっと分かってなかったが解説スライドを見て納得した.

F - Hotel

横から首出してコードを投げたらそれが想定解になってた.題材が無限ホテルだったので,だったら最初から長さ無限にしませんか?と提案したが厳密性が怪しくなると数学のプロたちに言われて却下されちゃった.

G - Min Nim

渡されて 2 分で解けたのでこれは簡単ですね~って言ってたが,他の人はすんなりはいかなかったみたい.

H - Count Pseudo-Palindromes

最初の提案時からわからず解説 AC.最初  O(N \log ^2 N) 解法が想定で,そのときは長さが良い擬回文の列挙に帰着して列挙に  O(N \log ^2 N) かけるというものだった.その後まったく方針の違う  O(N\sqrt{N}) やら  O(N \log N) 解法がたくさんでてきたので改めて元の想定解の列挙パートを考えてみたところ,線形に落とせることに気が付いたのでそれを報告.なんやかんやあって今の形式に落ち着いた.K の満点を除けばこれが最難問だと思っていて,本番は正解者が出るかどうか怪しいと思っていたが実際は 1AC 出ていてすごい.線形で解けるのが地味に推しポイントその 2.

I - Maximize Array

Writer.簡単枠が足りてなかったみたいだったで適当に考えてたら案外よさげなのが生えたので提案.簡単だけどちゃんと考察をしないとペナしやすい問題になってよかった.

J - Colored Complete Graph

もともと  N\leq 200 とかで,そのときは乱択で雑に通してしまった.ちゃんと想定解の考察を要求しましょうということで  N\leq 50000 に.AtCoderインタラクティブの問題で質問回数が  10^5 回以上ある問題が見つからなかったので心配だったが特に指摘されることはなかった.

K - (mod HW+1)

この問題が 100 点の部分点も含めて誰にも解かれない問題になってしまった.100 点の部分点はすごい難しいというわけではなく正解者も出るだろうと予想していたのでびっくり.101 点の存在にみんなビビっちゃったのかなあ.準備段階で,もともと W が  H=W バージョン(部分点 100 点)の問題を提案していて,それはそこそこ時間はかかったが自力で解けた.お正月の帰省中に  H\neq W バージョンをふと考えてみるとなんか解ける気がしたので,W/T に解けるかもしれないと報告.実査にはその後がめちゃくちゃ大変で,ひたすらコーナーケースつぶしをしていた.特に  (H,W,R)=(11,13,0) が不可能なことの証明が大変で,この証明にかなりの時間を割くことになった.最終的に自分はプログラムを書いて枝刈り全探索をすることで証明した.

L - Random Mex

制約を無視すればいろんな解法がありそう.実際自分は各テストケースに対して  O(M \log N) の解法が最初思いついていたし,他の準備陣からもいろんな解法が出ていた.しばらくして,答えがスターリング数を用いると簡潔な式で表現できることが分かったので,だったらそれを要求するような制約にしませんかと提案.結果的に今の制約になった.一応 OEIS を使えばエスパーすることができることは確認していたし,数え上げ得意な人多いからもうちょっと解かれると予想していた.

M - Vivid Colors

自分が問題を渡されたときは,題材に倣って  r,g,b\lt 256 の制約だった.最初の式変形は wolfram alpha に投げるとやってくれて,あとは選ぶベクトルを乱択することで犯罪 AC をした.他のテスターも乱択で通していたので,しぶしぶ制約を強化して乱択を通りにくくするように.想定解は実装も含めてかなり難しいと思う.sotanishy 君の別解はすごい.

N - Do Not Turn Back

サークルの活動の後に問題を教えてもらい少し考えて分からず,すぐに解法を聞いてしまった.典型っぽさはあるが難しいと思う(自力では無理な気がする).この問題を BMBM で解けちゃうのはびっくりした.

O - 0100 Insertion

判定問題を 5 時間位考えたが分からず解説 AC.必要十分条件がすっきりしていてすごい.その条件が前から見ていかないとダメだったので,じゃあ最初からひっくり返しておきませんかと提案した.結果 1AC になった.

P - Sub Brackets

この問題が参加者の中で一番評判が良かったんじゃないかなと思う.見た目(制約も含めて?)は区間 DP っぽさがあるが想定解はフローで,そのギャップに驚いている人たちがたくさんいた.自分も区間 DP にまんまとハマってしまったし,コンテスト中に実際にハマっていた人もいたようだった . N の制約は何でもよかったが,区間 DP っぽさを出すために  N\leq 500 ということに.

自分がやったこと

  • C:Writer
  • D:Writer
  • H: O(N) 解法の提案
  • I:Writer
  • K: H\neq W バージョンの提案
  • L: O(N^2) 解法を要求することを提案
  • M: r,g,b の制約を強化することを提案
  • O:0010 を 0100 に変更することを提案

その他

TUPC の前の ARC で無事 karinohito 君が入橙していた.これにより toam, sotanishy, karinohito 大学同期 3 人が揃って橙の状態で TUPC を迎えることができた.sotanishy 君が来月からいなくなってしまうので,その前に全員が揃う瞬間ができて本当に良かった.

以上,ご参加ありがとうございました.

AHC028 参加記

11 位.

懇親会 + 賞金 1.5 万円ゲット!やったぁ

 

開始 30 分で考えたこと

  • 作る文字列があらかじめ決まっていたら,DP で最適解が作れる
  • 文字列の長さを最短にするのが必ずしもいいとは限らない
  • 作る縁起の良い文字列の順番を決め打ったら,DP で最適解が作れる
  • いい感じの順番を探したい -> ビームサーチ?焼きなまし?
  • 2-opt がうまくいかなそう(T1 -> T2 の相性は良くても T2 -> T1 の相性は良いわけではない)
  • 他の近傍が思いつかないので,とりあえずビームサーチにしよう
  • ビームサーチだと,もともと作りにくい文字列たちが残っちゃわない? -> 各文字列に対して,"作りやすさ" (値が小さいほど簡単)を定義して,ビームサーチ中にはコストから作りやすさを引くことにすればちょうどいいのでは?

あとはひたすら実装.ビームサーチは速い言語の方が有利なので c++ で書くことにした.

(上に書いた考察は解説放送で大体同じことを言っていた(作りやすさは解説放送の base cost みたいなもの))

 

実装

まずビームサーチを高速化するのを念頭に, T_i の次に  T_j を付けるときに必要な遷移コストを前計算した. dp\lbrack i\rbrack \lbrack j\rbrack \lbrack (x_i,y_i)\rbrack \lbrack (x_j,y_j)\rbrack で「 T_i の末尾の文字がマス (x_i,y_i) で終わっていた場合に, T_j の末尾の文字をマス (x_j,y_j) で終わらせるために必要なコスト」みたいな感じで DP を定義した.

ビームサーチの状態としては,「すでに決定している  T の順序,および最後のマス」を持った.

文字列  t に対する作りやすさ(base cost)は,とりあえず「マス  (x,y) から始めたとき文字列 t を作るために必要な最小コスト」を  N^2 個すべての  (x,y) に対して求め,それらの平均値とした.

 

いつもは python を書いているため,慣れない言語でかなり実装にてこずったが,2:07:14 に初提出 (1081686 点).このとき 10 位.

初提出のビーム幅を間違えて 2 にしていたので,70 にしてから再度提出 (1092374 点).6 位に浮上.

 

残り時間は高速化と base cost の計算方法を変えたりしていた.base cost を平均値の 0.8 倍くらいにすると 1097399 点.これがコンテスト中最高点だった.

 

解説放送を見ると,base cost は「全ての  (x,y) に対する最小コスト」の最小値としていて,これに変えてみると 1099433 点になってコンテスト中順位 8 位まで上がった.コンテスト中にこの計算方法も思いついていたので悔しい.seed=0,1 でよくならなかったので諦めていたが,とりあえず出してみればよかった.

 

感想

自分の解法がちゃんとはまり,AHC 過去最高順位も取れてうれしい.とても面白い問題だった.懇親会楽しみ~

AHC028 参加記

11 位.

懇親会 + 賞金 1.5 万円ゲット!やったぁ

 

開始 30 分で考えたこと

  • 作る文字列があらかじめ決まっていたら,DP で最適解が作れる
  • 文字列の長さを最短にするのが必ずしもいいとは限らない
  • 作る縁起の良い文字列の順番を決め打ったら,DP で最適解が作れる
  • いい感じの順番を探したい -> ビームサーチ?焼きなまし?
  • 2-opt がうまくいかなそう(T1 -> T2 の相性は良くても T2 -> T1 の相性は良いわけではない)
  • 他の近傍が思いつかないので,とりあえずビームサーチにしよう
  • ビームサーチだと,もともと作りにくい文字列たちが残っちゃわない? -> 各文字列に対して,"作りやすさ" (値が小さいほど簡単)を定義して,ビームサーチ中にはコストから作りやすさを引くことにすればちょうどいいのでは?

あとはひたすら実装.ビームサーチは速い言語の方が有利なので c++ で書くことにした.

(上に書いた考察は解説放送で大体同じことを言っていた(作りやすさは解説放送の base cost みたいなもの))

 

実装

まずビームサーチを高速化するのを念頭に, T_i の次に  T_j を付けるときに必要な遷移コストを前計算した. dp\lbrack i\rbrack \lbrack j\rbrack \lbrack (x_i,y_i)\rbrack \lbrack (x_j,y_j)\rbrack で「 T_i の末尾の文字がマス (x_i,y_i) で終わっていた場合に, T_j の末尾の文字をマス (x_j,y_j) で終わらせるために必要なコスト」みたいな感じで DP を定義した.

ビームサーチの状態としては,「すでに決定している  T の順序,および最後のマス」を持った.

文字列  t に対する作りやすさ(base cost)は,とりあえず「マス  (x,y) から始めたとき文字列 t を作るために必要な最小コスト」を  N^2 個すべての  (x,y) に対して求め,それらの平均値とした.

 

いつもは python を書いているため,慣れない言語でかなり実装にてこずったが,2:07:14 に初提出 (1081686 点).このとき 10 位.

初提出のビーム幅を間違えて 2 にしていたので,70 にしてから再度提出 (1092374 点).6 位に浮上.

 

残り時間は高速化と base cost の計算方法を変えたりしていた.base cost を平均値の 0.8 倍くらいにすると 1097399 点.これがコンテスト中最高点だった.

 

解説放送を見ると,base cost は「全ての  (x,y) に対する最小コスト」の最小値としていて,これに変えてみると 1099433 点になってコンテスト中順位 8 位まで上がった.コンテスト中にこの計算方法も思いついていたので悔しい.seed=0,1 でよくならなかったので諦めていたが,とりあえず出してみればよかった.

 

感想

自分の解法がちゃんとはまり,AHC 過去最高順位も取れてうれしい.とても面白い問題だった.懇親会楽しみ~

第10回 Asprova プログラミングコンテスト(AHC023)参加記

48 位.

方針

大まかな方針:

  • 通路を決める(図の赤線)
  • 細長い部屋を作る(図の青線)
  • 各部屋ごとに,配置する作物を貪欲に決める

通路・部屋の決定

以下のような山登り法を実施

  • 通路にも部屋にも属さないマスが存在するまで以下を繰り返す
    • いずれかの部屋を破壊して,その部屋を作り直す(伸ばせるだけ伸ばす)
      • もとの部屋のサイズより大きければそれを採用
    • たまに,通路のマスを増やしたり減らしたりする(ただし通路が連結になるように増減させる)

作物の決定

各部屋ごとに,配置する作物を区間 DP で決めていった.

 dp \lbrack C \rbrack \lbrack L\rbrack \lbrack R\rbrack= L 日目から R 日目まで,サイズが  C の部屋に配置できる作物のスコアの合計の最大値」

としたとき,以下のような漸化式が成り立つ.

 (S,D)=(L,R) となる残っている作物の個数を  M とすると

  •  C \leq M のとき  dp\lbrack C \rbrack \lbrack L\rbrack \lbrack R\rbrack=C(R-L+1)
  •  C\gt M のとき  \displaystyle dp\lbrack C \rbrack \lbrack L\rbrack \lbrack R\rbrack=M(R-L+1)+ \max_{L\leq mid\lt R}(dp\lbrack C-M \rbrack \lbrack L\rbrack \lbrack mid\rbrack+dp\lbrack C-M \rbrack \lbrack mid+1\rbrack \lbrack R\rbrack)

これに加えて, (S,D)=(L+1,R) であるような作物を  L 日目に植えるようにした遷移も加えるとスコアが結構上がった(4.5 M くらい).すなわち, (S,D)=(L+1,R) となる残っている作物の個数を  M' とすると

 \displaystyle dp\lbrack C \rbrack \lbrack L\rbrack \lbrack R\rbrack=M(R-L+1) + M'(R-L) + \max_{L\leq mid\lt R}(dp\lbrack C-M-M' \rbrack \lbrack L\rbrack \lbrack mid\rbrack+dp\lbrack C-M-M' \rbrack \lbrack mid+1\rbrack \lbrack R\rbrack)

みたいな遷移も追加した. 計算量がやばくて,部屋ごとに DP テーブルを再計算する必要があるので,全体で  O(T^3 HW) かかってしまう.python だと無理そうだったので途中から c++ に書き換えた.DP の復元がめんどい.

感想

  • 40.7 M くらいで頭打ちになってしまってそれ以降ほとんど何もできなかったのが残念.
  • ほとんどアルゴで殴ってしまってヒューリっぽいことができなかったのが残念.
  • 上位陣は焼いていてすごい.こんなの焼けるんですね~(焼いている解法ツイート流れてきたけど何言ってるのかさっぱりだった)

ICPC 2023 国内予選参加記

ICPC 2023 Asia Yokohama Regional 国内予選に Aobayama_doctors として出ました.

チームについて

チームメンバー

チーム名の doctors の由来は「医者になる人」×2 + 「博士になる人」×1 から.

当日まで

私と Ryota が学業で多忙だったため,チーム練習はほとんどできず模擬予選のみ.圧倒的に練習がたりず,模擬予選の結果も不安が残るものだったため焦っていた.事前に決めていたことは,幾何と構文解析が出たら私が担当することくらい.実装力に自信があったので,重そうなやつは引き受けるとも言ってあった.

主な使用言語が私が Python で私以外が C++ だったので,ライブラリはそれぞれが持っていくことにした.

当日(コンテスト開始前)

14 時頃に会場となる研究室に到着.各チームが集まって場所決めをした後にプリンターのチェックをして,リハーサルをした.

その後序盤の立ち回りについて話し合った.元々 A,B 問題を私以外の二人に任せて私が C 問題以降を考察することにしていた.だが,模擬予選の序盤がうまくいかなかったこと,FA を取ると企業賞が貰えること,去年の ICPC の B 問題を数日前に私が Python で解き直したら結構素早く書けたことが合わさって,A,B 問題を私が担当することに急遽決めた.

リハーサルの後結構時間があって落ち着かなかったので,他のチームの人やこたつがめさんとしゃべっていた.

暇だったので,パソコンの目の前にこたつがめさんをお守り用に置いておくことにした.(コンテスト中はすっかりこたつがめさんの存在を忘れており,こたつがめさんの存在を再び思い出したのはコンテスト後だったんだけどね......)

コンテストについて

A 問題

Python を使える環境を整えた後,FA を狙って爆速でコードを書いた.やるだけなので 30 秒くらいで書き上げて AC(2:54).一秒差で FA を取れていた.やったね!

B 問題

あみだくじをみて,TUPC の J - AMidA を思い出した.問題文の読解に苦労して題意をつかむのに時間がかかった.やることは追加する場所が  O(NM) 箇所あるのでそれらを全探索する.各追加場所に対して  O(N+M) で結果が分かるので全体で  O(NM(N+M))Python のスライスを使うと実装がちょっと楽になっていいね.AC (17:39).

def solve_amida(n,xs):
  P=list(range(n))
  for x in xs:
    P[x],P[x+1]=P[x+1],P[x]
  return P

while True:
  n,m,p,q=map(int,input().split())
  if n==m==p==q==0:
    exit()
  X=list(map(int,input().split()))
  X=[i-1 for i in X]
  p-=1
  q-=1
  first=solve_amida(n,X)
  if first.index(p)==q:
    print('OK')
    continue
  ans=[]
  for j in range(m+1):
    for i in range(n-1):
      X2=X[:j]+[i]+X[j:]
      res=solve_amida(n,X2)
      if res.index(p)==q:
        ans.append((i+1,j))
  if ans:
    print(*ans[0])
  else:
    print('NG')

C 問題

私が A, B を解いている間に二人が C の考察を進めてくれていたが,やや詰まっていたらしい.Dispersion さんがコード書いて実験したいとのことなので席を譲り,私と Ryota は紙で考察をしていた.Ryota がマス目を市松模様に塗って黒のマスを適当にシフトする方針を思いついていて,これが筋が良さそうだと思ったのでもう少し考察を詰めた.半分くらいずらすといけそうな気がしたので Dispersion さんから席を譲ってもらい実装.

( N=5 の場合. x+y が奇数のものだけを順番にシフトした.)

00 01 02 03 04       00 13 02 15 04
05 06 07 08 09       17 06 19 08 21
10 11 12 13 14  -->  10 23 12 01 14
15 16 17 18 19       03 16 05 18 07
20 21 22 23 24       20 09 22 11 24

これが正しいかどうかを判定するコードを書くと  N が 4 の倍数のときだけ合わないらしい.Ryota N=4 で合わない理由をすぐに教えてくれたので,試しに  N が 4 の倍数のときだけ奇数行目を反転してみるとなんか合った.

( N=4 の場合.シフトしたのちに奇数行目を反転させた.)

00 01 02 03       00 09 02 11       11 02 09 00
04 05 06 07  -->  12 05 14 07  -->  12 05 14 07
08 09 10 11       08 01 10 03       03 10 01 08
12 13 14 15       04 13 06 15       04 13 06 15

無事 AC(48:44).

D 問題

C 問題の実装で手こずっている間に Dispersion さんがほとんど考察を終わらせてくれていた.答えが 7 以下になるのを見抜いていて,答えが 6 以下かどうかを全探索すればよさそうとのことだった.大雑把な計算量が  100^5/120\times 100\times 6 くらいで Python だとやばそうだということになり,C++ で bitset を使って実装することにした.Dispersion さんが実装することになったが,実装方法に苦労していそうだったので途中からずっと横で見て適宜口を出すなどをしていた.実装ミスもほとんどなく,デバッグもほとんどせずに AC(73:21).Dispersion さんとハイタッチして喜んだ.この時点で大体 10 位.

E 問題

初手で引いた方針が悪く, O(N^3) からずっと落ちなかった. dp\lbrack i\rbrack \lbrack x\rbrack \lbrack y\rbrack i 番目の人が解いた数が  (x,y) のときの最小の変更コストとするとして,高速化とかもいろいろ考えたけどダメだった.

F 問題

E の考察がなかなか進まないので途中から F も並行して考えていた.多角形の凸法に含まれない部分について,その両端の 2 つの辺が平行じゃなかったら不可能,そうじゃないときは可能になりそうだと Dispersion さんが予想して,これが正しそうに感じたので実装.幾何ライブラリの凸包とかを写経して,サンプルがあったので提出したが WA.なにがいけないのかわからずそのままコンテスト終了.

結果全体 19 位(大学内 1 位).予選突破できた.

コンテスト後

チームメイトと反省会をした.E,F は解けなかったものの,D までのムーブがほぼ完ぺきでよかったねとお互いを褒め合った.三人がそれぞれ活躍していて,チーム戦のよさが出ていてよかった.

そのあと他のチームと軽く感想戦をした.E 問題の想定  O(N^2) 解法を 1 年生が思いついてすげ~~と感動していた.言われてみれば典型だけど気づけなくて悔しい.F については条件が不十分だと指摘されて確かにとなった.

(追記)F は方針自体は合っていそうで,私の実装が間違っているだけな気がしてきました.

サークルで解散した後は打ち上げをした.

感想

去年惜しい結果で予選敗退していたので,今年初めて横浜に行けて凄いうれしい!学業がやばくて横浜の対策は全くできそうにないので,横浜は楽しむことを第一にしていければいいかな~

yukicoder contest 391 - F : Factorial Paths

問題

 (1,1) から  (H,W) 経路数が  N! となるような  H\times W のグリッド( H,W\leq 2000)を求めよ.

解法

本解説と違ったので書く.

下の図のような感じで,経路数が  n となるようなできるだけ小さいグリッドを用意して,それらを左上から順に並べるようにする.

イメージ

以下のような条件のもとでグリッドを全探索をして,それぞれの経路数を求めたところ, 400 以下の各正整数  k に対して,経路数が  k となるようなものが見つかった.

  • サイズが  h\times w (2\leq w\leq h\leq 7)
  • 黒マスが  5 個以下

経路数が同じものが複数個見つかったときは,そのうち  (h,w) が最小になるものを採用した. k\leq 10 はこんな感じ

1
..
#.

2
..
..

3
...
...

4
..#
...
#..

5
..#
...
...

6
...
...
...

7
....
....
.#..

8
...#
....
#...

9
....
....
#...

10
....
....
.... 

得られた  400 個の長方形のサイズの度数分布はつぎのようになった.

  • (2, 2): 2
  • (2, 3): 1
  • (3, 3): 3
  • (3, 4): 4
  • (4, 4): 9
  • (4, 5): 15
  • (4, 6): 4
  • (5, 5): 27
  • (5, 6): 55
  • (5, 7): 4
  • (6, 6): 109
  • (6, 7): 166
  • (7, 7): 1

これらを縦横の長さが均等になるように反転させたりしてつなげると,  N=400 のときに  (H,W)=(1955,1956) が構築できた.

最後に  N=10 の場合のグリッドを示す.

..###################
#..##################
#....################
##....###############
####...##############
#####...#############
######...############
######.....##########
########...##########
########.....########
##########..#########
##########...########
##########.....######
############....#####
#############....####
###############...###
###############...###
###############......
#################....
#################....