ABC 432 C 問題の解き方と説明
導入
AtCoder ABC 432 の C 問題と公式解説の難易度が高めだったので、私なりの解法とその説明を書き残したいと思います。
問題
全文:ABC 432 C - Candy Tribulation
問題文を読み解くと、
方針
まず子供
飴を交換するごとに重量が
子供
ここで
すべての
考察を進めると、以下の2つの条件が満たされれば共通部分が存在することがわかります。

図 1: 各子供の飴の重量
-
区間条件:すべての
の区間S_i が重なっていること[L_i, R_i] -
剰余条件:すべての
の初項S_i がL_i において同値であること\mod d
実装
def solve1(n, x, y, a):
g_l = max(a) * x
g_r = min(a) * y
# 区間条件を満たすか
if g_r < g_l:
return -1
d = y - x
# 共通部分が存在すれば、その最大値 g_r を選べば大きな飴の個数を最大化できる
g = g_r
ans = 0
for a_i in a:
# 剰余条件を満たすか
if (g - x * a_i) % d != 0:
return -1
ans += (g - x * a_i) // d
return ans
詳しい証明
共通部分の形
共通部分が存在する場合、その数列は「
これを以下のように
ただし
区間条件
すべての区間が重なっている部分が集合
全区間のうち最大の左端
剰余条件
共通部分
例えば「歩幅が同じ人々が、スタート地点に歩幅未満のズレがある状態で歩き始める」という状況を考えます。
この人々はどれだけ歩いても互いの足跡を踏むことがありません。互いの足跡を踏めるのはスタート地点の差がちょうど歩幅の倍数であるときのみです。

図 2: 剰余条件が満たされない(スタート地点の差が
この条件(剰余条件)は以下の式で表せます。
大きな飴の数の最大化
問題では大きな飴を渡せる個数の最大値が求められています。
各子供に渡す大きな飴の数を
上述したコードにおいては、剰余条件の確認と
まとめ
導入でも述べたように「等差数列の共通部分を求める」という問いに帰着できれば単純な問題なのですが、
問題文からこれを読み解くのが難しく、理屈が単純ゆえに数式による証明も難しくなりがちな問題でした。
公式解説やけんちょんさんによる解説もありますので、本記事も問題を読み解く一助になれば幸いです。
Discussion