AtCoder Beginner Contest 256 メモ(A-D)
今回の結果
3AC
C問題が解き方が分からず。
D問題を見たら頑張れば解ける範囲かなと思ったのでCを飛ばす判断をして、時間ギリギリでなんとかACできた。
A - 2^N
Difficulty: 7
問題文
制約
0≤N≤30 -
は整数であるN
入力
入力は以下の形式で標準入力から与えられる。
出力
答えを出力せよ。
入出力例
入力例 1
3
出力例 1
8
入力例 2
30
出力例 2
1073741824
参加中に考えたこと
256回目だから、2のN乗に関する問題は出るだろうなという予想はしてた。A問題で出てきたのでシンプルな問題になってる。
pow関数を使うのが一番楽だけど誤差が出るのが心配。制約の最大値30で試して誤差はなかったので大丈夫だろうということでpow関数を使って提出。
powはdouble型なので整数型でキャストしてあげる。答えの後ろに
pow関数を使わずループでも解けるけど、N=0の時には1となるようにちょっと工夫は必要。
あとNが大きいと答えがint型に収まらないのでlong long型を使うこと。
B - Batters
Difficulty: 81
問題文
高橋君は野球をモチーフにしたゲームを作ろうとしましたが、うまくコードが書けなくて困っています。
高橋君の代わりに次の問題を解くプログラムを作ってください。
マス
また、整数
正の整数からなる数列
- マス
に駒を0 個置く。1 - マス上のすべての駒を番号が
大きいマスに進める。言い換えると、駒がマスA_i にあればその駒をマスx に移動する。x+A_i
ただし移動先のマスが存在しない (すなわち がx+A_i 以上になる) 駒たちに関しては、それらを取り除いて4 に取り除いた個数を加算する。P
すべての操作を行った後の
制約
1≤N≤100 1≤A_i≤4 - 入力される値はすべて整数
入力
入力は以下の形式で標準入力から与えられる。
出力
操作終了時点での
入出力例
入力例 1
4
1 1 3 2
出力例 1
3
入力例 2
3
1 1 1
出力例 2
0
入力例 3
10
2 2 4 1 1 1 4 2 2 1
出力例 3
8
参加中に考えたこと
問題文の説明の通りにコードを書くだけ。
マスは4つしかないけど配列で持っておいたほうが処理は楽。操作1と操作2を続けてすることから、1つのマスに2つ以上の駒が入らないことは分かる。
C - Filling 3x3 array
Difficulty: 541
問題文
縦横
-
について、上からi=1,2,3 行目に書きこんだ数の和がi になる。h_i -
について、左からj=1,2,3 列目に書きこんだ数の和がj になる。w_j
例えば
さて、条件を満たす書きこみ方は全部で何通り存在しますか?
制約
3≤h_1,h_2,h_3,w_1,w_2,w_3≤30 - 入力される値はすべて整数
入力
入力は以下の形式で標準入力から与えられる。
出力
条件を満たす書きこみ方が何通りあるかを出力せよ。
入出力例
入力例 1
3 4 6 3 3 7
出力例 1
1
入力例 2
3 4 5 6 7 8
出力例 2
0
入力例 3
5 13 10 6 13 9
出力例 3
120
入力例 4
20 25 30 22 29 24
出力例 4
30613
参加中に考えたこと
魔法陣の一片は高々30なので答えはそんなに大きな数にはならなそう。
各マスに入るのは正の整数であることと制約の制約から整理すると、各マスの値に入り得る数値1~28であることは分かる。
ここから先の進め方が閃かなかったのでスキップ。
考察・感想
数字が小さいので全探索でも解けるのかを考えてみた。
純粋に9重ループで計算すると計算量は
少し考えてみると、各行または列において2箇所の値が決まっていると、もう1つはhあるいはwからその2つの値を引いた値となる。
このあたりは公式解説のほうが詳しく書かれているが、結論として左上の4つの値が決まれば、残りの5つのマスは自動的に決まる。右下については、途中に求めた4つの値を使って計算ができ、その値が作ることができる場合にカウントする。
左上4つのマスを4重ループにして、ループの中で判定する処理を行なう方法であれば計算量は
途中考えたように多重ループの中の範囲をシビアにする必要はなく、4重ループの全て1~30としてもACできた。
D - Union of Interval
Difficulty: 546
問題文
実数
制約
1≤N≤2×10^5 1≤L_i<R_i≤2×10^5 - 入力に含まれる値は全て整数である
入力
入力は以下の形式で標準入力から与えられる。
出力
入出力例
入力例 1
3
10 20
20 30
40 50
出力例 1
10 30
40 50
入力例 2
3
10 40
30 60
20 50
出力例 2
10 60
参加中に考えたこと
以前解いた数直線の問題で、区間の両端のデータだけを使って解く方法があったので、同じ方法で解くことを考えた。L,Rをpairで持たせて、左から処理したいのでソートしておく。
和集合を求めるにあたって何を用いるのかに悩んだ。スタックとかも考えたが値によって取り出す順番が違うので失敗。左端の値で比較したいので最終的にはLとRの2つのmapを用いることにした。
また、この問題では右半開区間しかないので、ある半開区間のRともう1つの半開区間のLが同じ値の場合は1つの区間とみなせる。
ソートした右半開区間を左から順に読んでいってシミュレーションしていけばよさそう。
区間の範囲内か範囲外かで和集合を分けるか分けないかを決めていくという方法で提出したらWAになった。
数直線のケースのどれかの考慮が漏れてるので整理し直す。
2つの右半開区間
-
交差していないL1 < R1 < L2 < R2 -
交差しているL1 < L2 < R1 < R2 -
※ソート済なのでこのケースはない(2と同じとみなす)L2 < L1 < R2 < R1 -
交差していないが、1つの範囲の中に他方が含まれているL1 < L2 < R2 < L1
のどれかのはず。
4の考慮が抜けてそう、、と思ったらその通りだったのでこのケースの処理を直して再提出するとACできた。
書いたコードがかなりゴリ押し感がある。
考察・感想
LとRをペアで持たないと整合性が崩れるかと思ったけど、この問題ではその心配は必要なくて、(1)位置、(2)LかRか、の2つをペアで持たせることで事足りる。
左から見ていくと Lの数 < Rの数 となることはないと考えていい。
あとは公式解説にある「問題の読み替え」が分かりやすい。
Discussion