Exercise本番は遅かったので不参加。250がいつもよりちょっと難しめ、500は普通、1000はいつもより簡単に感じた。NetworkXZeroOne'o'と'x'からのみなる文字列を送信する。ネットワークの不調のため文字列のいくつかの部分が壊れてしまい、受信側では、"o?x?"や"????x"のような状態になっている。この文字列を復元する。文字列のすべての偶数部分列に含まれる'o'と'x'の数は等しい。少なくとも一つの'?'の前、もしくは後ろは、'o'か'x'になっているはず。それとは違う文字を'?'に入れてやればいい。これを'?'が無くなるまで繰り返す。今回はサイズが小さいので愚直に文字全体をなめていっても間に合う。サイズが大きい場合は、queueをつかって、新しくfixした部分の周りだけ見るという工夫(priority_queueを使ってdijkstraを高速化するときと同じようなやり方)をすると高速化できる。NetworkXOneTimePadバイナリの平文('0'と'1'からのみ構成される平文)を、あるキー文字列を使って暗号化する。平文の集合と、暗号文の集合が与えられるので、キーとなりうる文字列の数を求める。キーとなりうるとは、すべての暗号文は、ある平文とキーから構成することができる場合を指す。要するに、暗号化を写像fに見立てた場合、fがonto(surjective)であればいい。方針としては、平文集合[i]から暗号集合[0]が作られていると考えて、キーをfix。そのキーに対する写像fがontoであるなら、そのキーは妥当と判断。これをすべてのiで試す。O(n^4)解で書いたけど、適切な場所でpre-calculationすれば、O(n^3)で解ける。NetworkXMessageRecoveryアルファベットの大文字、小文字のみからなる文字列xがある。この文字列のなかに同じ文字は2回以上現れない。xの部分文字列(必ずしも連続していない)が複数個与えられるので、xが何かを予想する。xが複数個考えられる場合は、辞書順がもっとも小さいものを出力する。"edcba"それぞれの部分列から、どの文字がどの文字より先に現れるべきかが分かる。ある文字aが別の文字bに先行する場合は、aからbへの有向枝があると考えてグラフを構成する。これをトポロジカルソートしてあげればいい。トポロジカル順序の決定は辞書順が小さいものから行うようにする。Practicesの続き。昔のSRMは比較的簡単なようで、なんとか自力で解けた。1の問題は簡単だったけど、この辺のレベルになると、なかなか面白い問題が集まっている。確率の問題をパターン化してストックしたいので、方針・実装方法とかをまとめておく。153分散システム(N個のcomponentから構成される)を用いて、各端末に固有IDを割り振る。分散システム同士は通信を行わない。それぞれのcomponentは、assignments[i]個のIDを端末に割り振らないといけない。以下2つの方針で実装した場合のIDの衝突確率を求める。各componentはmemoryを持っており、自身が割り当てたIDを記憶できる。よって自身のタスクではcollisionは発生しない。各componentはmemoryを持っていない。自身のタスクでもcollisionが発生しうる。2.は使っていないIDを選んでいくだけ。分子がデクリメントされていくような分数の積。1.はcomponentの中では、衝突が起きないように人為的な選択ができるので、(同一component内では)分母もデクリメントされていく。結果、1.の方がcollisionが起きにくくなる。この問題は、数学色が強い。18*8のチェス盤上に一駒のknightが任意の場所に置かれている。knightは一様な確率で8方向(通常のknightの動きと同じ)のいずれかにランダムに移動する。knightをN回移動させたときに、knightがチェス盤上に残っている確率を求める。見、むずかしそうだなと思った。DPを使えば、i回移動させたとき各マス上にknightがいる確率が分かれば、(i+1)回目移動させたときにあるマス上にknightがいる確率は計算できる。これをN回、すべてのマス上で行えばよいので、O(8*8*8*N)で計算できる。199ポーカーで賭けをするとき、レートが5倍にあがる。raceという確率的なミニゲームをおこなう。raceでは一人最高でも1つのチップしか勝ち取ることはできない。ゲームの状態が与えられるので、各プレイヤーがチップを勝ち取る確率を求める。一度チップを勝ち取ったプレイヤーは、さらにチップを勝ち取ることはないので、そのプレイヤーは以後のターンでは除外して考えることができる。(・・・・)))のような再帰で書ける。div="">実はこの問題、メモ化の機構は不要なことが分かった。7・・・と減っていく。3.6*10^6回程度再帰されるだけなので、単なる再帰でもOKだったようだ。この階乗の形で木をイメージすることが出来ていなかったので、良い勉強になった。242A君と、B君がサイコロをNa回、Nb回ずつ振る。(それぞれ最高で200回)。100までのいずれかのpips(目)が書いている。サイコロを振った合計値を得点とするとき、A君がB君より高い得点を取る確率を求める。サイコロの各面がでる確率は一様分布に従う。A君の得点がある数字になる確率を部分和問題の要領で計算する。結果は、サイズ20,000程度のバッファdp[]に格納。今度はB君について同じことをする。今度は引き算の方向に処理をする。i=1,2,...の和。そのあと、B君の得点がi未満になる確率をpos[i]に格納。pos[i]の総和を解とする。相変わらず、部分和問題のときにtmp用のバッファを用意するのがまだまだ成長してないなと思った。下から上じゃなくて、上からしたに見て行けば矛盾なくin-placeで更新できるので、今度からは気を付ける。2433つの問題を解いてオンラインジャッジをするコンテストがある。コンテストの参加者は問題を解くのに必要とした時間に応じて点数が与えられる。ジャッジに落ちた問題の点数は0となる。それぞれの参加者の3つの問題に対する点数と、ジャッジをパスする確率が与えられる。あなたの点数が与えられるので、あなたが上位5位以内に入る確率を求める。これは、なかなか悩んだ。どこを状態数として保持するか。i人目までをみたときに、あなたより高い点数がj人いる確率をdp[i][j]として保持すると、うまく計算できる。(Easy)確率論の問題を解いた。確率論のtutorial+レベル別問題まとめみたいなのがあったのでやってみた。force系の問題が多かった。難しい問題はなかったが、面白そうな話題があったので紹介。1741年がN日から成り立つ世界がある。何人の人を集めれば、同じ誕生日の人が少なくとも2人出てくる確率がP(%)以上になるか?というような問題。問題文にあるように、「クラスに23人いれば、同じ誕生日の人がいる確率は50%を超える。」というのは有名な話。counter-intuitiveな確率の話として、覚えておいて損はないかも。155この法則は知らなかった。日常生活にでてくる数字の多くは、以下の確率に従う。