diverta 2019 Programming Contest 2
Updated:
diverta 2019 Programming Contest 2
Source codesPermalink
SolutionsPermalink
A - Ball DistributionPermalink
以下を出力する。
N−K(K>1),0(K=0).
B - Picking UpPermalink
0-indexed とする。 0≤i,j≤N−1, i≠j に対し (xi−xjyi−yj) の数が一番多いものを (pq) にするのが一番コストが少なくて済む。そのコストは N−cnt である。 O(N2) で求まる。
C - Successive SubtractionPermalink
解答Permalink
0-indexed とする。 Ai たちは昇順であると仮定して良い。このとき、 ±A0±A1±A2±⋯±AN−1 が候補の数字であるが( ± の組み合わせは任意)、このうち「全て + 」と「全て − 」はできない。操作の際に x−y とすると、その後の x,y の符号が同じになることはありえないからである。逆にそれ以外は全てできる(後述)。つまり答えは −A0±A1±A2±⋯±AN−1+AN−1 である。真ん中の ± は正になるように決めればよろしい。
その構成法: まず now=A0 とする。次に + の符号を選んだ Ai に対し (now,Ai) を出力し、 now←now−Ai とする。次に now2=AN−1 とする。次に − の符号を選んだ Ai に対し (now2,Ai) を出力し、 now2←now2−Ai とする。最後に (now2,now) を出力する。
ポイントPermalink
符号を先に決めうちするのがポイント。 これで実装の場合分けを避けることができ、楽になる。
D - Squirrel MerchantPermalink
前半:問題の分割Permalink
まずこの問題は 2 つのパートに分けることができる。
- A で金属に両替して、 B でどんぐりに全て交換する
- B で金属に両替して、 A でどんぐりに全て交換する
これが可能であるのは、 B でどんぐりと金属の rate が一致しているため、たとえ間違えたとしても可逆であり、自由に交換ができるからである。中間地点ではどんぐりが多ければ多いほどいい。したがって 2 つの問題に分けることができる。
後半: DPPermalink
あとは DP で処理すればよろしい。
DP[i]=i 個のどんぐりを最初に持っている時に、両替の末に持つことのできるどんぐりの個数の最大値
と定める。初期状態: DP[0]=0, otherwise DP[i]=0 。答え: DP[N] 。遷移: i=1,…,N に対し、 DP[i]=max(i,DP[i−gk]+gl,DP[i−sk]+sl,DP[i−bk]+bl). ここで index ははみ出さない場合のみ max をとるものと規約する。
ポイントPermalink
前半はわかったのだが、後半 3 重ループは無理だなと思っていたら DP だった。いやはや。
E - Balanced PilesPermalink
前半: D=1 の場合Permalink
DP によるのはほぼ明らかだろう。問題は状態をどのように管理するかである。まず現在の高さの最大値 x は持っておかねばならない。次にその個数 y も考察する必要がある。ここでポイントは 同じ高さに対しては操作する相対的な順番がすでに決まっているものと仮定する ことである。すると初期状態は N! 個を分けて考察する必要があるが、最終状態が N! 個の重複があるので、実は打ち消し合う。したがってこの仮定を入れて計算しても同じ結果が得られる。
以上の元で、状態の遷移の係数を考察する。単純に (x,y) と書く。
- まず (0,N) からスタートするが、ここから先への遷移は (0,N)→(1,1) の 1 通りしかありえない。
- 次に 1≤x≤H−1, 1≤y≤N に対し、 (x,y)→(x+1,1) への遷移は、最小値のうち一番優先度の高いものを操作するので、 1 通りしかない。
- 最後に 1≤x≤H, 1≤y≤N−1 に対し、 (x,y)→(x,y+1) への遷移は (y+1) 通りある。なぜなら最小値のうち一番優先度の高いものを操作し、最大値と同じ高さにするのであるが、そこで相対的な優先度の決め方が (y+1) 通りあるからである。
この結果、 3. の遷移を 2. に擬似的にまとめることが可能である。つまり (0,N)→(1,∗)→(2,∗)→⋯→(H,1)→(H,N) であるが、最初の遷移が 1 通り、そのほかの遷移は (1+2!+⋯+N!) 通り、最後の遷移は N! 通りである。これで O(H) で計算する道筋が整った。
後半: D が一般の場合Permalink
X=1+2!+⋯+N! とする。すると (x,∗)→(x+d,∗) where d≤D に対して多重度 X の辺が張られていると思えばよろしい。累積和を使って更新が可能である。
DP[i]=(i,∗) での場合の数、
sum[i]=∑j<iDP[i].
と定める。すると 1. は初期状態に落とし込むことができて、 DP[i]=1 (1≤i≤D), otherwise DP[i]=0. 答え: N!×DP[H] ((H,1)→(H,N) を考慮してある)。 遷移: i=2,…,H に対し、 sum[i]=sum[i−1]+DP[i−1],DP[i]+=(sum[i]−sum[i−D])X. ここで index は 1 以上の際に有効であるとする。
ポイントPermalink
これは多重度を分けて考えないといけないので独力では正解に至れなかったのではないかと思う。
F - Diverta CityPermalink
解答Permalink
1-indexed とする。再帰的に構成するものとする。 n 個数の点からなる完全グラフ Gn であって、条件を充たすものを求めたとする。 Gn のハミルトンパスの最長値に 1 を足した数を Mn とおく。
V は正の数の集合であって、任意の x,y∈V に対し x+y と x が相異なるものとする。具体的には前から貪欲に構成ができて V={1,2,4,7,12,…} のようになる。
このとき、 Gn に頂点 n+1 を加えるのであるが、この時 i と n+1 の長さを MnV[i] と定めると必ずうまくいく。その理由:まず n+1 を通らないハミルトンパスの長さは Mn 未満な一方で n+1 を通るハミルトンパスの長さは Mn 以上になるのでこれらが一致することはない。さらに V に課せられた制約により、 n+1 を通るハミルトンパスは n+1 を通る辺を 1 つかまたは 2 つしか通らないのであるが、それらの長さの和は異なっている。また n+1 を通るハミルトンパスで n+1 を経由しない辺の長さの和は Mn 未満であるので、これらを加えてもやはり異なる値を取ることが保証される。
ポイントPermalink
これ昔に出た東大の学部入試に真ん中に 1 を 99 個数並ばせる問題に発想がかなり近いと思う。
OthersPermalink
しばらくレーティングは下がっていくけどまぁいいだろう。