問題
D - All Your Paths are Different Lengths
考えたこと
なんかbit的な考え方?という臭いがしたのでとりあえずとおき、辺の長さをとしていい感じの有効グラフを構築してみます。
頂点間に長さのパスができあがっているので 残りの長さのパスを重複しないように作れないか考えます。
まずは直近のの辺をどっかの頂点から頂点に生やしてみます。
頂点へのパス長はですのでこいつに生やすと頂点から頂点に長さのパスが出来上がります。
頂点の選び方ですが、 なるべく多くのパスをカバーしたいので 頂点から逆に見ていくとよさそうです。 パス長が以上になるならパスして次の頂点を検討。
頂点に辺を生やすと残りのパス長はとなります。 次はの辺を生やします。またから見てやって以上にならないものを選ぶ。 と繰り返していけばよさそうです。
これで本当にうまくいでしょうか?このやり方だと重複しないようにパスを作れるので、 個の範囲でパスを任意に増やすことができればオッケーです。
頂点に生やすと個パス長が増えます。 以外の頂点に生やせば最大で 個のパスを増やすことができます。 好きなを選べますのでこの範囲で任意の数のパス長を増やせます。
コード
static void Solve() { var L = Sarray()[0]; var N = 0; for (var i = 0; i < 20; ++i) if ((L & (1 << i)) != 0) N = i; var graph = Enumerable.Range(0, N).Select(_ => new List<(int to, int c)>()).ToArray(); for (var i = 0; i < N; ++i) { graph[i].Add((i + 1, 0)); graph[i].Add((i + 1, (int)Pow(2, i))); } var last = L - 1; var now = (int)Pow(2, N); var pos = N - 1; while (now <= last) { var left = (int)Pow(2, pos) - 1; if (now + left <= last) { graph[pos].Add((N, now)); now += left + 1; } --pos; } var m = graph.Sum(g => g.Count); WriteLine($"{N + 1} {m}"); for (var i = 0; i < N; ++i) { foreach (var tc in graph[i]) { WriteLine($"{i + 1} {tc.to + 1} {tc.c}"); } } }
Submission #15199902 - AtCoder Beginner Contest 108
背景
パスを追加していくところの理解に時間がかかったのでメモ