2020年12月31日木曜日
2020年のまとめ
2020年11月26日木曜日
Codingame「Fall Challenge 2020」
Codingameの「Fall Challenge 2020」に参加しました。ルールはtsukammoさんのブログ記事が分かりやすいと思います。英語のルールを読むのは自分には結構大変で、この記事でルール概要を把握してから挑めたのはありがたかった。正直なところ、この記事がなかったら参加していたか怪しいです。
結果は、全体513位/7011人、Gold League内で433位/464人でした。最終日にGold Leagueにはなんとか上がれたものの、そこで何もできず終わった感じですね。初参加にしてはまあまあ良かったとみるか、まだまだ頑張りが足りなかったとみるか。微妙なところですね。
始めるとき、密かに目標していたのは、(あまり交流があるわけではないですが)ツイッター上で良く見かけるprd_xxxさん、AT274さんでした。prd_xxxさんは偶然(後述しますが、偶然としか言いようがない)上回れましたが、AT274さんはLegend League入りを達成され、ライバル視できるような状況には全くなりませんでした。それはちょっと悔しいです。
各リーグで書いたもの
・WOOD2
・WOOD1
・BRONZE
・SILVER
・GOLD
やったこと
良かったこと
反省点
2020年10月4日日曜日
Hokkaido University Programming Contest 2019 Day 2 D: Two Colors Sort
問題はこちら。
積み残していたこの問題をACしました。
解説pdfの通り、蟻本で「個数制限付き部分和問題」と紹介されている問題に帰着できるのですが、bitsetによる高速化ができることもあり、計算量解析が話題になりました。(参考:noshi91さんの記事)
……が、今試してみたところ、特に工夫せず、Pythonのbit演算で普通にDPすれば間に合いました! Pythonで2秒程度なので、十分速いですね。
今は、Kiriさんのこんな記事もあり、自分も(単純なものなら)0と1のみのDPテーブルを一つの数を代用する方法に慣れてきたと思いますが、当時は分かってなかったんですね。
2020年10月2日金曜日
グラフの直径と半径
九月からブログ再開すると言っていたのに、いつのまにか10月になってしまった。なんでもいいから書こう。(とはいえ、こんなので良いのかな……)
を解いたが、最初、WAを出してしまった。
まず、答えを書く(解説pdf通りです)と、
・グラフの直径:出来上がるグラフ上で最も遠い2点間の距離
・グラフの中心: もっとも遠い頂点への距離がもっとも小さい頂点
・グラフの半径:グラフの中心から最も遠い頂点への距離
としたとき、
・最大値:直径の和+1
・最小値:半径の和+1もしくは、元の直径のうち大きい方
となる。
そこまでは分かったのだけど、自分は、半径=(直径+1)/2(切り捨て)と勘違いした(これは木なら成り立つはず)ためWAを出してしまった。変な先入観を持つのは避けなければ。
次のようなグラフを考えれば、これは成り立ちませんね。
このグラフだと直径=2、半径=2となる模様。
2020年9月4日金曜日
九月
2020年7月31日金曜日
yukicoder contest 242
コンテストへのリンク
コンテスト後のツイート
No.1017 Reiwa Sequence
解説AC。鳩の巣原理を使うんだろうと思っても、使い方が意外と難しい。n個の要素を-1か+1を選ぶのは$2^n$通りなので早く発散しそう……と思えば、それらの和の値で抑えるのは自然なのだけれど。鳩の巣原理を使いなれていると思いつきやすいんだろうなぁ。
その後の実装をどうするかも悩んだ。
単純な$3^N$では間に合わないけど、半分全列挙するのは面倒だし……と。結局、解説の「計算方法(1)」の方法で実装したけど、この実装もちょっと思いつきにくい気がする。
たとえば、indexの集合 S={1,2,4}, T={2,4,6,7}とで和が一致するとき、2,4という重複要素はどうするんだろう……と思ってしまった。この場合、同じ要素を足しても打ち消し合うのでそこは0にして、$A_1, -A_6,-A_7$が0になる。冷静に考えれば分かるけど……。
2020年7月29日水曜日
April Fools Day Contest 2020
コンテストへのリンク
コンテスト後のツイート
C. ...And after happily lived ever they
D. Again?
E. Jordan Smiley
from PIL import Image import numpy as np im = np.array(Image.open('jor.png')) x=13.5 ANS=[[0]*64 for i in range(64)] for i in range(64): for j in range(64): if (im[int(i*x+x/2)][int(j*x+x/2)]==[0,0,0]).all(): ANS[i][j]=0 else: ANS[i][j]=1
yukicoder April Fool Contest 2020
コンテストへのリンク
No.3063 幅優先探索
No.3070 ソラニン
Codeforces Round #630 (Div. 2)
コンテストへのリンク
コンテスト後のツイート
D. Walk on Matrix
E. Height All the Same
F. Independent Set
G. No Monotone Triples
2020年7月20日月曜日
JOI 感謝祭 2020
双子のコンテストは解説がしっかりしてることもあって好きなのだけど、最近は良い結果が出せていませんね。
コンテストへのリンク
解説PDF
コンテスト後のツイート
鏡のような分割(Mirror-like Division)
塗り箸2(Chopsticks 2)
で、今回は、「大きくしたい値」と「小さくしたい値」の個数が同じなので、中央値を境界にすると、境界より下にある「大きくしたい値」の個数と、境界より上にある「小さくしたい値」の個数は同じになり、条件を満たします。
こういうタイプの問題で中央値を考えるのは一つの定石だと思うので、思いつけるようになりたい。
2020年7月16日木曜日
AtCoder Beginner Contest 160
コンテストへのリンク
コンテスト後のツイート
F - Distributing Integers
この問題でも全方位木DPの実装にかなりの時間を取られている。
コンテスト中TLEしてしまったのは、全方位木DPをしようとしているのに、前計算を利用できていないところがあり、二乗の計算量になってしまったためでした。
これに気付けないのはまずい。
復習のためと思ってもう一度書き直してみたのだけど、やはりかなり時間がかかってしまった上、また二乗で提出して一回TLEしてしまった……。
全方位木DPは辺に関するDPとして理解している(一回目は葉から根の方向に、二回目は根から葉の方向に値を決める)のだけど、DPテーブルとしてはDP[node]=valueとするため、一回目と二回目で見る部分が違ってしまうのが混乱のもとだと思う。
(一回目では、DP[x]でnode x→P[x]の辺に関する値を求めるため、xの子供たちを見れば良いけど、二回目では、DP[x]でnode P[x]→xの辺に関する値を求めるので、P[x]に繋がる辺たちを調べることになる。それが紛らわしい)
これでいつも戸惑ってしまうのだけど、どうにかできないだろうか……。ちゃんとライブラリ化しなくちゃいけないのかな。
2020年7月15日水曜日
Thanks Kosen 2020
今見たら、Gも解けるべき問題でした。ただし、実装は大変ですね。
コンテストへのリンク
コンテスト後のツイート
E - インターン
F - 卒業RTA
G - 答辞
累積和と二分探索を使えば、「各indexが左端のとき、右端はどこより先か」、「各indexが右端のとき、左端はどこより先か」が分かる。そう整理すると、このブログで何度か引用しているアルメリアさんのこの記事に帰着できる……と思って見に行ったら、この問題も例題として扱っていましたね。
何度か似た問題を解いたおかげとはいえ、自力でこの方法だと気付けたのは嬉しい。ただ、実装にはかなり時間がかかってしまうんですよね……。このタイプを早く解くのは厳しい。
Codeforces Round #629 (Div. 3)
Unratedだと(時々Ratedでも)、詰まったときに寝てしまうことがあるのは良くないですね。そもそもこのEは詰まらずに解けておくべき問題でした。
コンテストへのリンク
E. Tree Queries
F. Make k Equal
2020年7月13日月曜日
Educational Codeforces Round 84 (Rated for Div. 2)
こういうことを何度もやっているため、Educational Codeforcesには苦手意識がある。
コンテストへのリンク
コンテスト後のツイート
D. Infinite Path
E. Count The Blocks
たとえば、n=1の長さ1と、n=2の長さ2で答えは同じになる。一般に、n=kの長さlとn=k+1の長さl+1で答えが同じになることは、長さlのブロックに一つ数字を加えて長さl+1のブロックにすることで、全単射が構成できることから分かる。
なので、各nについて、長さ1のブロックの個数を求めれば良い。
余事象を使って漸化式を立てる方針が分かりやすいと思う(が、自分はコンテスト中この方針でやろうとして立式を失敗した)。
が、端かそうでないかで場合分けすれば、そのまま立式することもできる。
F. AND Segments
2020年7月10日金曜日
AtCoder Beginner Contest 159
コンテストへのリンク
F - Knapsack for All Segments
Kick Start Round A 2020
コンテスト中もTrie木を使うのかな、とは思ったようですが……。
コンテストへのリンク
コンテスト後のツイート
Bundling
import sys input = sys.stdin.readline T = int(input()) for testcases in range(T): N,K=map(int,input().split()) # Trie木 Next_node_id=[[-1]*26] # "A"~"Z"それぞれについて、対応する次のノードのid Parent_id=[-1] # 親ノード Depth=[0] # Trieのノードの深さ Count=[0] # Trieのノードの重複度 Nodes_id=1 # 以下、標準入力で与えられたN個の文字列を追加する実装 for i in range(N): S=input().strip() L=len(S) NOW=0 for s in S: NEXT=ord(s)-65 if Next_node_id[NOW][NEXT]==-1: # Nodeを追加する場合 Next_node_id[NOW][NEXT]=Nodes_id Next_node_id.append([-1]*26) Parent_id.append(NOW) Depth.append(Depth[NOW]+1) Count.append(0) NOW=Nodes_id Nodes_id+=1 else: # 追加しない場合 NOW=Next_node_id[NOW][NEXT] Count[NOW]+=1 # 終端に印を付ける TOP_SORT=sorted([(dep,id) for id,dep in enumerate(Depth)],reverse=True) Rest=[0]*len(TOP_SORT) ANS=0 for dep,n in TOP_SORT: c=Count[n]+Rest[n] ANS+=Depth[n]*(c//K) Rest[Parent_id[n]]+=c%K print("Case #"+str(testcases+1)+": "+str(ANS))
2020年7月8日水曜日
AtCoder Grand Contest 043
コンテストへのリンク
コンテスト後のツイート
B - 123 Triangle
C - Giant Graph
公式解説動画を見てAC。ゲーム以外の場面でGrundy数を使う問題は初めて見たと思う。ゲーム以外の問題で使える概念だと思っていなかったので驚いた。けんちょんさんやアルメリアさんもブログで似た感想を書いていますね。
D - Merge Triplets
さて、こういう「操作の結果出来上がるものが何通りありますか」という問題では、操作過程をまともに追いかけてはいけないと痛感している。まずはじめに「こういう順列を作れますか?」という判定問題を解くのだ。
を心に留めておきたい。
コンテスト中もコンテスト後も、操作を追いかける方向でしか考えなかったし、判定問題を解こうという気持ちになれなかった……。強く反省。
なお、DPの立式の部分はアルメリアさんの方法が分かりやすいと思います。公式解説の方法やけんちょんさんの記事の方法はそれに比べるとやや難しい(理解するのに苦労しました)。
2020年7月6日月曜日
OUPC β
コンテストへのリンク
コンテスト後のツイート
Product Grid
Increasing Path
ビブンケイスウ
2020年7月3日金曜日
TopCoder Single Round Match 781
いや、これは解けなくちゃいけない問題でしたね。こういう、それほど難しくない構築は取りたい……。
Div1 Easy EpicPartition
公式解説を読むと、色々方法がある、と書いてある(としか書いてない)。kmjpさんの解説もあるけど、色々な方法があるらしいので、別な方法を考えた。
cの位置を決めることを考える。
kmjpさんの解説にもある通り、cを埋めた残りが全て二個連続していれば(適当な四個を前半二個、後半二個に分けて)"abba"とすることで、aとbの和を一致させることができる。
なので、できるだけ連続している位置にcを埋めたい。
ここで、"c"を埋め込むときの平均値を考える。
たとえば、N=6のとき、全体の和は300、"c"の和は150で8個なので、平均は18.75。なので、18と19を中心に、15~22を"c"にしようとすると2だけ不足する。のえ、最後の22を24に変えれば辻褄が合う。
一般にこういう構成で良いことは立式すれば証明できる(できた)。
1~24xの中から1/3を"c"にするとすると、"c"の和は$144x^2+6x$で、18.5x中心に構成した和は$144x^2+4x$。後者の構成の最大の数は18x+4xなので、それを1~24xの中で最大の数である24xにすれば辻褄が合うことが分かる。
以下、システムテストを通ったコード。
class EpicPartition(): def createPartition(self, N): if N%4!=0: return "" k=N*6 ALL=k*(k+1)//2 CK=(ALL//2)//(k//3) ANS=["a"]*k ANS[-1]="c" for i in range(CK-k//6,CK+k//6-1): ANS[i]="c" f=0 for i in range(k): if f< k//3 and ANS[i]!="c": if f%2==0: ANS[i]="a" else: ANS[i]="b" f+=1 elif ANS[i]!="c": if f%2==1: ANS[i]="a" else: ANS[i]="b" f+=1 return "".join(ANS)
2020年7月2日木曜日
Codeforces Global Round 7
FもACしようと思った(F2は厳しくてもF1は結構解かれているので、F1だけでも)のですが、公式解説を読んでも理解できなかったので飛ばします。無念。
コンテストへのリンク
コンテスト後のツイート
D. Prefix-Suffix Palindrome
E. Bombs
アルメリアさんの解説記事を読んでAC。
問題を正しく把握するのも結構難しいけれど、把握したうえで、
・答えがある値kより大きいか?
という判定問題にすれば良いと気付くのが難しい。ただ、これさえできれば後は結構自然か。
クエリが進むごとに答えがだんだん小さくなっていくので、
・尺取り法(風)
に計算量を抑えることができるのも、なるほど、という感じ。
解説通り書いて提出したらPyPy3での初ACだったようですが、(非再帰遅延セグ木を持っていれば)計算時間にも余裕があるし、自慢にはなりませんね。
2020年6月29日月曜日
Codeforces Round #628 (Div. 2)
コンテスト中は、EやFはあまり考えずに寝てしまった……。
コンテストへのリンク
コンテスト後のツイート
E. Ehab's REAL Number Theory Problem
F. Ehab's Last Theorem
2020年6月25日木曜日
パナソニックプログラミングコンテスト2020
コンテストへのリンク
コンテスト後のツイート
B - Bishop
C - Sqrt Inequality
D - String Equivalence
E - Three Substrings
F - Fractal Shortest Path
AGCっぽい問題に見えるので、なんでABCで出題したんだろう? というのはちょっと不思議。確かに、発想すべき点は「避けなければならないブロックは高々一つ」くらいなので、発想より実装よりの問題、ということなのかな……。
FII Code 2020 Round #3
コンテストへのリンク
コンテスト後のツイート
(このブログの記事は、主に、当時の自分のツイートを参考にして書いています。なら、そのツイートも載せておいた方が良いのでは? と思ったので、今後はできるだけ載せます)
Confused Robot
追記)ダブリングなしで「S一回進んでも動かなくなる回数」は求められることに気付きました。グリッドの各マスについて、「S一回でどのマスにいくか」を調べておけば、
・S一回後に自分自身に戻るマスは0回(以後Sを実行しても動かなくなる)
・S一回後に0へ行くマスが1回
という風にして、DFS/BFSで求められますね。
ただ、それを求めても、「S一回進んでも動かなくなるギリギリの回数」は最大N*M回あると思うので、O(N*M*S)では無理な気が……。(やっぱりダブリングが必要では?)
Double Palindromes
2020年6月23日火曜日
Codeforces Round #627 (Div. 3)
コンテストへのリンク
A. Yet Another Tetris Problem
B. Yet Another Palindrome Problem
C. Frog Jumps
D. Pair of Topics
E. Sleeping Schedule
F. Maximum White Subtree
2020年6月22日月曜日
Educational Codeforces Round 83 (Rated for Div. 2)
コンテストへのリンク
B. Bogosort
C. Adding Powers
D. Count the Arrays
E. Array Shrinking
F. Attack on Red Kingdom
G. Autocompletion
2020年6月15日月曜日
日立製作所 社会システム事業部 プログラミングコンテスト2020
コンテストへのリンク
C - ThREE
D - Manga Market
E - Odd Sum Rectangles
F - Preserve Diameter
あとは確かに木DPをするだけなのだけど、その実装が難しくて戸惑った。
2020年6月6日土曜日
TopCoder Single Round Match 780
Div1 Easy BeatTheStar
点数が1点もらえる試合~N点もらえる試合が一試合ずつあり、二人のうちどちらかにその得点が入る。G点の試合が勝負の分かれ目になる(つまり、その試合を勝てたら合計得点でも勝ち、負ければ合計得点でも負け)確率は? という問題。余事象を考えると、G点の試合以外で、片方の点数が合計何点以下ならそういう状況にならないか、が分かる。なので、片方の点数がそれ以下になる場合をDPで求め、$2^{N-1}$で割って、1から引く。
Python内fastestだったようなので、自分のコードはここで見ることができます。
Div1 Medium Prominence
コンテスト中は問題内容を把握できていなかった。kmjpさんのブログ記事で問題内容を把握しました。内容を把握できれば解法を理解するのはそんなに難しくないですね。
kmjpさんの解法では前半パートにsetを使っていますが、公式解説を読むと平衡二分木は必要ない模様。左右から山を見ていけばできるのですね。
後半パートもセグメント木ではなくSparse Tableを使えばO(N)になるのかな。(Pythonでは実行時間が厳しそうだし、実装はサボります。とはいえ、一応O(N)なので、上手く書けば通ってもおかしくはないですか)
AtCoder Beginner Contest 158
コンテストへのリンク
D - String Formation
一々文字列を反転させていたら時間がかかってしまうので、反転は最後にまとめて行い、文字列追加の際、反転の回数が偶数なら後ろに、奇数なら前に追加する。先頭への文字の追加は、Pythonならcollections.dequeを使う。
E - Divisible Substring
F - Removing Robots
2020年6月4日木曜日
Codeforces Round #626 (Div. 1, based on Moscow Open Olympiad in Informatics)
コンテストへのリンク
A. Unusual Competitions
B. Present
C. Instant Noodles
D. Reality Show
n人の人が順に並んでおり、それぞれにA[i](aggressiveness)と、C[i](cost)という整数が与えられている。index順にその人々を選ぶか、選ばないかを選択する。ただし、選ぶ場合は、A[i]の値が、今まで選んだ人の最小値より小さくなくてはならない。
各人を選んだ時に、コストと利益が発生する。コストはC[i]、利益はaggressivenessの値によって決まり、aの人を選んだ時、P[a]である。(Pは負の値も取る)
ただし、aggressiveness aの人が二人以上いた場合、そのうちの二人は戦い、残った一人のaggressivenessがa+1になる。この際、さらに利益がP[a+1]加算される。
利益 - コストを最大にするような選び方をしたときの利益 - コストの値を求める。
(解説と雑感)
公式解説でもある通り、まず、
・同じaggressivenessの人達を選んだなら、どのような順番に選んだとしても利益は同じになる
ことに気付くのがポイント。
設定が複雑なため分かりにくいけど、これは当たり前。
人が二人で戦う、というイメージではなく、値aのスライム二匹合成されると、a+1のスライムになる、というイメージで捉えると納得しやすいと思う。
(今後、人ではなくスライムと書くことにします)
このとき、indexを後ろから(aggressivenessの小さい方から)見ようと考えるのはまあ自然。そうすると、aggressiveness aのものを選んだら、今後a未満のものを考えなくてよくなる。
ただ、こう考えても、今までのスライムたちがどう合成され、どんなaggressivenessのスライムが残っているか、を一々考えていては大変。
だが、順番を変えても同じならば、一々合成させずとも、そのaggressivenessのスライムの個数さえ分かっていれば良い、と気付くのがもう一つのポイント。
つまり、
・DP[k][cnt] = Aのmaxがkで, そういうスライムがcnt匹いるときの利益 - costの最大値
としておいて、この値が更新されたときに、そのスライムを合成させたときを考えて、DP[k+1][cnt/2]などの値を更新していけば良い。(※)
計算時間ですが、今見ているスライムのaggressivenessがaのとき、a+1の部分の更新ヶ所は1/2、次の箇所は1/4……なので、(更新順番を工夫すれば?)大体二乗になるようです。
ただ、(※)を毎回行った自分の提出でもACできてしまいました。三乗でTLEになるだろうと思って投げたのですが。
更新箇所がそれほど多くないので、三乗(のはず)の書き方をしても通ることが多いのかも?
Div. 1のDということで身構えてしまうけど、解説を読むと意外と素直な問題でした。とはいえ、自力ACできるか、と言われると厳しそう。そもそも、コンテスト中にDを読みにいこうとはなかなか思えないですが……。
2020年5月30日土曜日
第4回 RECRUIT 日本橋ハーフマラソン 本戦(オープンコンテスト)
コンテストへのリンク
A - ハイパー覆面すごろく
B - ハイパーお掃除ロボット
yukicoder contest 240
ただ、たくさんWAを出しているのはよくないですね。yukicoderはペナルティなどないので、ついたくさん提出してしまう。
コンテストへのリンク
No.1006 Share an Integer
No.1008 Bench Craftsman
二回累積和を取るという方法は見たことなかったと思う。覚えておきたい。
2020年5月28日木曜日
2020 Humbleool Cup Prelims
Div.2の難易度で、全完しないとまずいセットだったのに、Hardをミスして落とす。
それでも、緑から青に戻ったけれど、これは出なくても良かったかなぁ、という気持ちになりました。
なお、MedはPython最速だったらしく公式ページに自分の実装が載っています。
CardDrawPoints
一応、システムテストを通ったコードを載せておきます。
class CardDrawPoints(): def expectedScore(self, count): LEN=len(count) if max(count)==0 or len(count)==1: return 0 LIST=[-1]*(1<<LEN) def calc(A): if LIST[A]!=-1: return LIST[A] rest=[0]*LEN NOW=0 for i in range(LEN): rest[i]=count[i] if A & (1<<i)!=0 and count[i]>0: NOW+=i rest[i]-=1 SUM=sum(rest) if SUM==0: return NOW ANS=float(0) for i in range(LEN): if A & (1<<i)!=0: continue else: ANS+=float(calc(A|(1<<i)))*rest[i]/SUM if NOW>ANS: LIST[A]=NOW return NOW else: LIST[A]=ANS return ANS for i in range((1<<LEN)-1,-1,-1): calc(i) return LIST[0]
2020年5月26日火曜日
みすだぶりゅ冬合宿わくわく競プロ大会
でも、復習したら、EもFも解けた気がしません……。頑張って検索すればいけたのかもしれないけど、自力では無理だったのは間違いない。
コンテストへのリンク
E - The Lowest Cost Trees
F - Was This Preordained?
2020年5月23日土曜日
CodeCraft-20 (Div. 2)
日本語の解説記事があったので、復習のときはEやFもACしよう、と思ったらかなり時間がかかってしまった……。
コンテストへのリンク
B. String Modification
C. Primitive Primes
D. Nash Matrix
E. Team Building
なお、この問題はPython/PyPyでは通せずKotlinでACしました。Kotlin Heroesが近付いているので、久々にKotlinを使ったけど、結構書きやすい!
F. Battalion Strength
2020年5月13日水曜日
Ozon Tech Challenge 2020 (Div.1 + Div.2, Rated, T-shirts + prizes!)
Fは嘘と思いつつ書いたら通ってしまって驚いた。悪あがきでもしてみるものですね。
コンテストへのリンク
B. Kuroni and Simple Strings
C. Kuroni and Impossible Calculation
D. Kuroni and the Celebration
E. Kuroni and the Score Distribution
F. Kuroni and the Punishment
2020年5月12日火曜日
Codeforces Round #625 (Div. 1, based on Technocup 2020 Final Round)
コンテストへのリンク
A. Journey Planning
B. Navigation System
C. World of Darkraft: Battle for Azathoth
・二次元平面上に図示→x, yの片方を固定
という流れは頻出(たとえば、SRM778のDiv1 Easyとか)。
特に、xとyが対称のとき、対称性を崩すことに躊躇いを覚えてしまいがちだけど、片方固定で解ける(計算量が落ちる)ことは良くあるので注意しておきたい。
その後の実装も大変だけど、できなくてはいけないのかなぁ。
なお、PyPyだと時間制限がやや厳しいです。
まつかわさんとのやりとりで、こういう知見が得られました。
INF=1<<31 と1<<31で型が違うのは、前者だと値が変化するかもしれないので、多少安全を取って型を決めているのかなぁ、と想像しています。(本当のところは分かりません)
D. Reachable Strings
2020年5月11日月曜日
AtCoder Beginner Contest 157
コンテストへのリンク
C - Guess The Number
E - Simple String Queries
F - Yakiniku Optimization Problem
2020年5月9日土曜日
butsurizuki Beginner Contest 003
全完で四位と良い出来だったと思う。
Fみたいな問題がABCで出ることはあるんでしょうか。
コンテストへのリンク
CROSS†SOUL
DEATH†ZIGOQ ~怒りの高速爆走野郎~
何でもダガー打ちゃいいってもんじゃねぇぞ†2020
"✝"
ゆるふわ競プロオンサイト #3 (Div. 1)
結構がんばったのだけど、難しい問題は解けず悔しい出来でした。
しかし、改めて復習すると、解けなかった問題はどれも解けそうになかった気がしてしまった。
コンテストへのリンク
解説スライドはここ
Bananas Multiplier
Banana Game
Sweets Distribution(Hard)
Yet Another Cake Division
Digit Sum Multiple
いや実際は、公式解説にも帰納法で証明できる旨は書いてあったので、それをちゃんと実行すれば分かったんですよね。
2020年5月2日土曜日
FII Code 2020 Round #2 (rated)
コンテストへのリンク
Big String
こういう問題は実験してみるしかなさそう。実験してみると、「Sの最後の文字」が、一回目だけS[-1]でそれ以後はS[0]と分かります。
Connecting the Graph
Disproportionate Tree
2020年4月30日木曜日
yukicoder contest 239
コンテストへのリンク
No.1000 Point Add and Array Add
No.1001 注文の多い順列
2020年4月29日水曜日
Kotlin Heroes: Episode 3
Dまでの四問解きましたが、問題を考えるより文法を検索していた時間の方が長かった印象。
ただ、Kotlinという言語に対する印象は結構良かった。
変なセミコロンを書いたりする必要がない(個人的にこれは凄く大きい!!!)し、型も結構省略できる。慣れたら書きやすそうな言語でした。
来月にはKotlin Heroes: Episode 4があるようなので、それに合わせてちょっと勉強しておきたい!
コンテストへのリンク
Codeforces Round #624 (Div. 3)
コンテストへのリンク
A. Add Odd or Subtract Even
B. WeirdSort
C. Perform the Combo
D. Three Integers
E. Construct the Binary Tree
F. Moving Points
2020年4月28日火曜日
Codeforces Round #623 (Div. 1, based on VK Cup 2019-2020 - Elimination Round, Engine)
コンテストへのリンク
A. Recommendations
B. Double Elimination
n試合後、[left番目~left+$2^n$)番目の人で、
D. Tourism
2020年4月20日月曜日
AtCoder Beginner Contest 156
この回は、Fで1caseのTLEが取れず五完でした。まあ、解法はあっていたので良いとします。
コンテストへのリンク
D - Bouquet
E - Roaming
F - Modularness
2020年4月8日水曜日
TopCoder Single Round Match 779
TopCoderのレートはあまり気にしていないつもりだったけど、緑に落ちたのは結構ショックだったので、もっと真剣にやらないと、と反省しました。
それに、このEasyは通さなくてはいけない問題だったので、そこも反省。
Div1 Easy ArraySorting
import bisect class ArraySorting(): def arraySort(self, A): N=len(A) DP=[1<<31]*N fr=[-1]*N # 復元用のリスト for i in range(N): a=A[i] pos=bisect.bisect_right(DP,a) DP[pos]=a if DP[pos-1]==1<<31: fr[i]=1 else: fr[i]=DP[pos-1] ANS=0 # LISの長さ for i in range(N): if DP[i]!=1<<31: ANS=i LASTV=DP[i] NEXT=LASTV B=[] for i in range(N-1,-1,-1): a=A[i] if a==NEXT: B.append(a) NEXT=fr[i] else: B.append(NEXT) return B[::-1]
yukicoder contest 238
コンテストへのリンク
No.994 ばらばらコイン
No.995 タピオカオイシクナーレ
No.996 Phnom Penh
No.997 Jumping Kangaroo
2020年4月7日火曜日
Codeforces Round #621 (Div. 1 + Div. 2)
コンテストへのリンク
B. Cow and Friend
C. Cow and Message
D. Cow and Fields
E. Cow and Treats
アルメリアさんのブログの解説記事を大いに参考にしてACしました。全く思いつかなかったのですが、解説されてみるとシンプル……。まず、
・左右の牛たちのために、草も左右で分ける
すら思いついてなかった。その上で、
・重複して数えないため、境界の一つ左側の草は必ず使う
という条件で数えるのが重要。
二点目はかなり難しそうだけど、一点目すら思いついていなかったのでコメントしにくい。でも、重複して数えないためにある要素を固定して数える、というのは重要そう。
ただ、やり方が分かっても実装が大変ですね。(実装部分は大体自力でやったこともあり)非常に苦労しました。
なお、PyPyだとアルメリアさんの実装そのままだとTLEすると思います(自分の場合はそうでした)。
ここの実装方針では、牛の総和・総積を取っていますが、ここも差分計算でできます。総和・総積のうち、今見ている草と一つ前の草以外については同じなので、その差分だけ計算すればOKです。(modが素数なので、積も逆元が取れます)
これをしたらACできました。
この変更をしても計算量のオーダーは変わらない……と思っていたのですが、これをすればO(nlogn)になりますね。
でも、実装は複雑になるので、C++使いにはあまり意味のない改善かも……。
2020年4月3日金曜日
AtCoder Beginner Contest 155
順位的にはひどいのですが、
Eが多く解かれているのには気付いていたけどDの解法は分かっていたので実装したかった、かつ、Dは若干Pythonに不利な問題だった、という事情があるので、まあ。
コンテストへのリンク
D - Pairs
E - Payment
F - Perils in Parallel
TopCoder Single Round Match 778
……けど、まぁ仕方ないかな、という気持ち。
Hack case作りに失敗したのは良くないけれど、Hackしようとした提出はシステムテストで落ちたので、「落ちそう」と思ったこと自体は間違ってなかった。
Div1 Easy KRectangleIntersection
2020年3月29日日曜日
第4回 RECRUIT 日本橋ハーフマラソン 予選
コンテストへのリンク
A - ゲーマーXとモノス大会
B - イラストレーターXと不思議なペン
FII Code 2020 Round #1 (rated for all)
CS Academyは動的配点(解いた人数によって配点が変化)など、コンテストの仕組みは面白いのですが、問題の不備などは結構多い印象です。
ただ、この一年の間にいつの間にかPyPyが使えるようになっていたのは嬉しかった。
このコンテストはCまでの三完。Dは実質的にはできていたのですが……。
コンテストへのリンク
As easy as ABC
Boring Operation
Cosmological Nightmare
Driveaway
2020年3月25日水曜日
yukicoder contest 237
Dは解けるべきだったし、今見るとFも難しくないですね。
コンテストへのリンク
No.987 N×Mマス計算(基本)
No.988 N×Mマス計算(総和)
No.989 N×Mマス計算(K以上)
No.990 N×Mマス計算(Kの倍数)
No.992 最長増加部分列の数え上げ
2020年3月16日月曜日
Codeforces Round #619 (Div. 2)
コンテストへのリンク
A. Three Strings
B. Motarack's Birthday
C. Ayoub's function
D. Time to Run
E. Nanosoft
2020年3月14日土曜日
Educational Codeforces Round 82 (Rated for Div. 2)
Eは解きたい難易度なんだけど、コンテスト後も自力ACできなかった。
コンテストへのリンク
A. Erasing Zeroes
B. National Project
C. Perfect Keyboard
D. Fill The Bag
E. Erase Subsequences
2020年3月12日木曜日
yukicoder contest 236
No.982 Add
No.983 Convolution
Codeforces Round #618 (Div. 1)
Cで、PyPyで出たTLEを除くことができず、C++に書き直した……というトラブルを除けば上出来。PyPyでTLEになっていた原因は、気付けば当たり前のことだったんですが、ちょっと気付きにくいことな気もするので、まあ仕方ないかなぁ、という気もしています。
コンテストへのリンク
A. Anu Has a Function
B. Aerodynamic
C. Water Balance
2020年3月10日火曜日
AtCoder Beginner Contest 154
B - I miss you...
C - Distinct or Not
D - Dice in Line
E - Almost Everywhere Zero
F - Many Many Paths
Codeforces Round #617 (Div. 3)
コンテストへのリンク
A. Array with Odd Sum
B. Food Buying
C. Yet Another Walking Robot
D. Fight with Monsters
E1. String Coloring (easy version)
E2. String Coloring (hard version)
本番では、LISと転倒数を混乱して、ライブラリを貼り間違えて悩んでいるうちに時間切れ……。
F. Berland Beauty
2020年3月6日金曜日
AIM Tech Poorly Prepared Contest (unrated, funny, Div. 1 preferred)
SRMの後だっけ、やってたからちょっと問題を見てみたけど、一問もできずに終わった。
コンテストへのリンク
A. Nash equilibrium
TopCoder Single Round Match 777
Div1 Easy PreviousOccurrence
class PreviousOccurrence(): def findValue(self, defaultValue, query): if query==0: return 0 if defaultValue==1: if query==1: return 1 else: return -1 NOW=0 LAST=[-1]*(5000000) ANS=0 while True: if LAST[NOW]==-1: NEXT=defaultValue LAST[NOW]=ANS ANS+=1 else: NEXT=ANS-LAST[NOW] LAST[NOW]=ANS ANS+=1 NOW=NEXT if NOW==query: return ANS break
Codeforces Round #616 (Div. 1)
Bは、考察で勘違いがあったものの、実装もミスってたためシステムテストを通って救われました……。
コンテストへのリンク
A. Mind Control
B. Irreducible Anagrams
C. Prefix Enlightenment
2020年2月28日金曜日
yukicoder contest 235
コンテストへのリンク
No.975 ミスターマックスバリュ
No.976 2 の 128 乗と M
No.977 アリス仕掛けの摩天楼
No.978 Fibonacci Convolution Easy
No.979 Longest Divisor Sequence
No.980 Fibonacci Convolution Hard
2020年2月24日月曜日
Educational Codeforces Round 81 (Rated for Div. 2)
それほど失敗した気はしなかったのに、順位はイマイチでした。
コンテストへのリンク
A. Display The Number
B. Infinite Prefixes
C. Obtain The String
D. Same GCDs
E. Permutation Separation
なお、PyPyで通すには制限時間も結構厳しく、手持ちの遅延Segment treeでは通らなかったため、Starry Sky tree(?)を使って通しました。
なお、ながたかなさんのブログ記事によると、そういったデータ構造を使わずとも通せるようですが……私は理解できていません。
F. Good Contest
2020年2月21日金曜日
AtCoder Beginner Contest 153
かなり簡単な回だったのでたいして順位は良くなかったけれど、これくらいで全完できれば自分としては満足。
コンテストへのリンク
A - Serval vs Monster
B - Common Raccoon vs Monster
C - Fennec vs Monster
D - Caracal vs Monster
E - Crested Ibis vs Monster
F - Silver Fox vs Monster
TopCoder Single Round Match 776
Div1 Easy EncloseArea
コンテスト中のコードを修正したものなので非常に読みにくいのですが、一応ACしたコードを載せておきます(載せるか迷ったのですが、ACした証拠として)。
class EncloseArea(): def enclose(self, A): if A%2!=0: return tuple() if A>2402: return tuple() ANS=[["."]*50 for i in range(50)] ANS[0][0]="/" ANS[0][1]="\\" ANS[1][0]="\\" ANS[1][1]="/" S=2 for i in range(1,49): if S==A: break ANS[i][i]="." ANS[i+1][i+1]="/" ANS[i][i+1]=ANS[i+1][i]="\\" S+=2 if S==A: A=[] for ans in ANS: A.append("".join(ans)) return tuple(A) NOWP=[0,1] NOWM=[1,0] def rewrite1(x,y): if ANS[x-1][y]==".": ANS[x-1][y]="/" else: ANS[x-1][y]="." ANS[x][y]="." ANS[x-1][y+1]="\\" ANS[x][y+1]="/" def rewrite2(x,y): if ANS[x][y-1]==".": ANS[x][y-1]="/" else: ANS[x][y-1]="." ANS[x][y]="." ANS[x+1][y-1]="\\" ANS[x+1][y]="/" while True: x,y=NOWP if 0<=x-1<50 and 0<=y+1<50: rewrite1(x,y) S+=2 NOWP[0]+=1 NOWP[1]+=1 if NOWP[0]==49 or NOWP[1]==49: MIN=min(NOWP) NOWP[0]-=MIN NOWP[1]-=MIN NOWP[1]+=2 if S==A: break x,y=NOWM if 0<=x+1<50 and 0<=y-1<50: rewrite2(x,y) S+=2 NOWM[0]+=1 NOWM[1]+=1 if NOWM[0]==49 or NOWM[1]==49: MIN=min(NOWM) NOWM[0]-=MIN NOWM[1]-=MIN NOWM[0]+=2 if S==A: break if S==A: A=[] for ans in ANS: A.append("".join(ans)) return tuple(A)
Div1 Medium StringRings
以下、ACしたコード。
class StringRings(): def expectedRings(self, A, B): ANS=0 for i in range(A): ANS+=1.0/(2*i+1) for i in range(B): ANS+=1.0/(A*2+i+1) return ANS
2020年2月20日木曜日
Codeforces Round #615 (Div. 3)
コンテストへのリンク
A. Collecting Coins
まず、三人の最大値までコインを割り振る。(割り振れなければNO)その後、3で割った余りが0ならばYES、そうでなければNO。
B. Collecting Packages
C. Product of Three Numbers
D. MEX maximizing
E. Obtain a Permutation
F. Three Paths on a Tree
そういう場合、中心Vに対して、V-a, V-b, V-cの距離が等しくなる三点a, b, cが存在するので、それらを取ればOKなのですね。(ながたかなさんのブログの記事を読んで気付きました)