あああああ

オタク & 競プロ

CODE FESTIVAL 2017 qual B - F Largest Smallest Cyclic Shift

editorialと違う気がしたので記事2個目

厳密じゃないです、ごめん(書けないので)

※全く証明にはなってないです。

代わりにまともに示してくれる or 反例をくれる人歓迎しています。

 

問題概要

atcoder.jp

 

a,b,cが全て存在する場合、f(T)はaで始まるので、もともとaだけの文字列があり、aとaの間にbまたはcをだいたい同じ個数ずつ挿入していきたい気持ちになります。

また、abcというsubstringの代わりに、acbというsubstringを作ってもf(T)が小さくなることはないことがわかります。

この考察をベースに考えます。

A%BでAをBで割ったあまりを表すこととします。

入力の和をNとします。

 

 

① 文字が1種類のとき

自明

 

 

② 文字が2種類のとき

aがA個、bがB個、cが0個とした問題が解ければ、a,b,cのどれが0個のときでも同様に解くことができる。

 

BがAの倍数のとき

(aを1個)+(bをB/A個)+(aを1個)+(bをB/A個)+...とするのが最適である。

 

BがAの倍数でないとき

(aを1個)+(bをfloor(B/A)個) という文字列xをA-(B%A)個 (=X個とする)

(aを1個)+(bをfloor(B/A)+1個) という文字列yをB%A個 (=Y個とする) 作り、

a->x, b->y, A->X, B->Yに置き換えて②を解いたものが最適である。

A+B>A=X+Yより、常にA+Bが減少していくので最大でもN回②を解けば終わることはわかる。(実際はgcdっぽいからlog?)

 

 

③文字が3種類のとき

aがA個、bがB個、cがC個とした問題を解くことを考える。

 

CがAの倍数のとき

(aを1個)+(cをC/A個)という文字列xをA個作り、

a->x, b->b, A->A, B->Bに置き換えて②を解いたものが最適である。

これは、abcよりacbの順のほうがf(T)が大きくなることと関係している。

 

以下、CがAの倍数でない時を考える。

Z=C%A, rem=A-Zとする。

 

Bがremの倍数のとき

(aを1個)+(cをfloor(C/A)個)+(bをB/rem個)という文字列yをrem個 

(aを1個)+(cをfloor(C/A)+1個) という文字列zをZ個  作り、

a->y, b->z, A->rem, B->Zに置き換えて②を解いたものが最適である。

これは、cをほぼ同数ずつaの直後に入れたくて、cが少ない方(floor(C/A)個の方)が辞書順では弱いのでそっちをbでできるだけ強化したいという感じ。

 

BがAの倍数でないとき

X=rem-(B%rem), Y=B%remとする。

(aを1個)+(cをfloor(C/A)個)+(bをfloor(B/rem)個)という文字列xをX個 

(aを1個)+(cをfloor(C/A)個)+(bをfloor(B/rem)+1個)という文字列yをY個 

(aを1個)+(cをfloor(C/A)+1個) という文字列zをZ個  作り、

a->x, b->y, c->z, A->X, B->Y, C->Zに置き換えて③を解いたものが最適である。

A+B+C>A=X+Y+Zより、常にA+B+Cが減少していくので最大でもN回③を解けば終わることはわかる。

 

ACコード

atcoder.jp

 

まあACしたのでたぶんあってます

 

まとめ

解説記事を書いてる人を尊敬します