あるエンジニアのAtCoder奮闘記

東京都港区にあるアミフィアブル株式会社のエンジニアが、AtCoderで解いた問題について振り返ったりしていく会社公認のブログです。

AtCoder ABC139 D - ModSum (Go)

irisruneです。暑さも多少和らいで雨も収まり過ごしやすくなったように思います。

問題

atcoder.jp

理論立てて考えないと、あまりに単純な解法すぎて戸惑うかもしれません。

package main

import (
    "bufio"
    "fmt"
    "os"
    "strconv"
)

var sc *bufio.Scanner

func nextInt() int {
    sc.Scan()
    i, e := strconv.Atoi(sc.Text())
    if e != nil {
        panic(e)
    }
    return i
}

func main() {
    sc = bufio.NewScanner(os.Stdin)
    sc.Split(bufio.ScanWords)
    n := nextInt()
    fmt.Println((n * (n - 1)) / 2)
}

結論から記すと、i\lt NのときP_i=i+1P_N=1とおくことで\sum^N_1M_i=1+2+\ldots+(N-1)+0=N(N-1)/2となり、これが最大値です。

M_iを最大化することを考えると、M_i=iとおくのが直感的によさそうに思えます。ただしM_Nに限ってはM_N\lt Nであることが推察できるのでとりあえずP_N=1,M_N=0とおきます。実はこれだけで上記の解になるわけですが、この道筋では最大値であることを証明するのは困難だと思います。

証明は公式解説にもある通りですが、まずP_i=1,2,\ldots,Nに対してM_i\leq0,1,\ldots,(N-1)であることから解の上界が求められ、それが上記の解と一致するため最大値であることが示せます。

雑記

  • 今週の予定は水曜にE問題、金曜に過去問(F問題が解けなければ)の予定です。