×
Copy
Open
Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
No. 332 数列をプレゼントに 原案,解説: camypaper
Slide 2
Slide 2 text
問題概要 • N 個の自然数からなる数列 A に総和が X であるような 部分列が存在するか判定せよ • 存在するならば部分列の一例を示せ • 制約 – 1 ≦ N ≦ 100 – 1 ≦ Ai ≦ 109 – Π Ai ≦10100 – 1 ≦ X ≦ 1012
Slide 3
Slide 3 text
考察 • これは経路復元つきのナップサック問題 • 典型的な解法は以下の 2 種類 – O(2N) で全探索 • N は最大で100なので間に合わない – 動的計画法を用いて O(NΣAi ) で解く • 最大で Σ Ai は109 以上になりうるのでやはり間に合わない • なんらかの制約や性質を利用する必要がある
Slide 4
Slide 4 text
怪しい制約 Π Ai ≦10100
Slide 5
Slide 5 text
考察 • 105 以上の値は最大でも 20 個しか存在しない – 存在するとすると Π Ai ≦10100 と矛盾 – 適当に大きい方から 20 個程度取り除いてみよう • A を降順に並び替えたあと先頭 20 個を取り除いた 数列 B について同様の問題を考えてみることにする – 制約は B の先頭の値を B0 としたとき, – 1 ≦ |B| ≦ 80 – 1 ≦ Bi ≦ B0 – 1 ≦ Σ log10 Bi ≦ 100 - 20log10 B0
Slide 6
Slide 6 text
考察 • 強いテストケースの気持ちになると、与えられた 制約下のもと ΣBi を最大化すればよいことがわかる • ΣBi を最大化するためにはどうすればよいか? – なるべく大きい数を可能な限り突っ込むのが最適 – 数列 A をある値 x が 20 + k 個 並んでいて他が 1 である数列 とする – ある k について x = 10100/(20+k) が ΣBi が最大になり, 右図はそのときの ΣBi を示す – ΣBi は最大でも 105 を超えない 0 10000 20000 30000 40000 50000 60000 70000 80000 0 5 10 15 20 ΣBi k 10^(100/(20 + k))k + (80 - k)
Slide 7
Slide 7 text
想定解法 (半分全列挙+DP) • Π Ai ≦10100 の制約より、降順に並べ直して先頭から 20 個程度 取り除いた数列 B の総和は 105 を超えない – これならば動的計画法を用いて解くことが可能 • 先頭 20 個程度ならば O(2n) かけて全探索可能 • 半分全列挙のようなことをすればよいことが分かる – こういうのを半分全列挙と呼んでいいのかは知らない
Slide 8
Slide 8 text
まとめ 1. 与えられる数列 A を降順に並べた数列を B とする 2. B の先頭 k 個を C ,残りを D とする 3. D の部分列で作れる数を O(|D|ΣDi ) で前計算 4. C の使い方を O(2|C|) で全探索 5. A の部分列に総和が X であるようなものが 存在するならば経路復元を行う • 適切な k を選ぶと3, 4 のどちらも 107 ステップ程度 – 定数倍はそこまできつくないので十分間に合う