少ない学びをせめて記録する

技術記録、競プロメモ、その他調べたことを書く @京都, twitter : @nehan_der_thal

AtCoder ABC128-F Frog Jump

k=A-Bを固定すれば大丈夫そうだったのですが、なぜかサンプルが合わず愚直解を書いてみる。一応出すも当然TLE。

N, = map(int, input().split())
xs = list(map(int, input().split()))
r = 0
for a in range(1, N-1):
    for b in range(1, N-2):
        if a <= b:
            continue
        if (N-1-a)%(a-b):
            continue
        n = (N-1-a)//(a-b)
        if a%(a-b) == 0:
            if a <= (a-b)*n:
                continue
        s = a
        t = xs[a]
        ps = [(a,xs[a])]
        for i in range(n):
            s -= b
            t += xs[s]
            ps.append((s,xs[s]))
            s += a
            ps.append((s,xs[s]))
            t += xs[s]
        print("k:%d, A:%d, B:%d"%(a-b,a,b))
        print(ps, t)
        r = max(r, t)
print(r)
k:3, A:4, B:1
[(4, 31), (3, -99), (7, -39), (6, -15), (10, 0)] -122
k:4, A:6, B:2
[(6, -15), (4, 31), (10, 0)] 16
k:2, A:6, B:4
[(6, -15), (2, 0), (8, 43), (4, 31), (10, 0)] 59
k:1, A:6, B:5
[(6, -15), (1, -4), (7, -39), (2, 0), (8, 43), (3, -99), (9, 18), (4, 31), (10, 0)] -65
k:3, A:7, B:4
[(7, -39), (3, -99), (10, 0)] -138
k:1, A:7, B:6
[(7, -39), (1, -4), (8, 43), (2, 0), (9, 18), (3, -99), (10, 0)] -81
k:2, A:8, B:6
[(8, 43), (2, 0), (10, 0)] 43
k:1, A:8, B:7
[(8, 43), (1, -4), (9, 18), (2, 0), (10, 0)] 57
k:1, A:9, B:8
[(9, 18), (1, -4), (10, 0)] 14
59

上を見るとやはりkを固定するので良さそう。kが同じ時に成り立つA候補で最小のものAmを計算する。 例えば上の例で、A-B=2の時 Am=6で

[(6, -15), (2, 0), (8, 43), (4, 31), (10, 0)] 59

並び替えると

[(6, -15), (4, 31), (8, 43), (2, 0), , , (10, 0)] 59

A-B=2, A=8では

[(8, 43), (2, 0), , , (10, 0)] 59

と先頭2つずつ除いていくとA'=A+1の場合も計算できるので、マイナスになるとゼロにする処理をしながら(k, Am)について処理すれば、(k,A)候補のうち最大の結果が得られる。 正解コード

N, = map(int, input().split())
xs = list(map(int, input().split()))
r = 0
for k in range(1, N):
    a = (N-1) % k
    for _ in range(1+(N-1-a)//k):
        b = a - k
        n = (N-1-a)//k
        if a <= b or a <= k:
            a += k
            continue
        if a%(a-b) == 0:
            if a <= (a-b)*n:
                a += k
                continue
    if a >= N-1:
        continue
    s1 = a
    s2 = n * (a-b)
    t = xs[s1]
    for i in range(n):
        s1 += a-b
        t += xs[s2]
        t = max(t,0)
        t += xs[s1]
        s2 -= a-b
    r = max(r, t)
print(r)

kからAmを出すのも少し大変だった。a = (N-1) % kでできるかと思ったら、b<0, b<a, a<=n-1の条件を満たす必要あり。 最後に葉が消えること考慮してあげないといけない。条件は(a%(a-b) == 0) and (a <= (a-b)*n)。 無駄にfor文回したが、a = (N-1) % k + hoge * kの形で書けそう。