ABC156

修論の影響で生活習慣が後ろ倒しになっていて,晩御飯を食べ終えて部屋に戻ってきてツイッターを見て「そういえば今日ABCだったじゃん!(23時)」って気づくのが3回くらい続いていて,久しぶりの参加になってしまった.
解説PDF:今回のはやけに丁寧で勉強になる.
[C]までは問題なくできた.[C]は全探索に気づかなったので平均取ってNで割ったのをintに丸めて,それとそれを+1したもので決勝戦をやる感じで書いた.計算量を見ましょう.

[D]

これがずっとできなくて終わってしまった.2^n mod 10^9+7は,

  • L=10^9+7p2^p<=Lを満たす最大のpとして,そのpを求める.
  • n=cp+dなるc,dを求める.
  • 2^n=(2^d)*(2^p)^cを計算する.

という方法でなんとか計算した(2^nnについてのforで計算するとO(10^9)になって間に合わないので,バッチを組むような感じ)けど二項係数がどうしても計算できなかった.
二項係数 (nCr) の計算方法:こうやって計算すれば良いらしい.フェルマーの小定理と繰り返し2乗法.
上で書いた2^nの方法は計算量がlogになってないから,やっぱり繰り返し2乗法でやりましょうって感じ.
しかしこれはちょっとライブラリを作りたくなる気持ちもわかるなあという感じ…

まとまってて良さげだと思った記事:「1000000007 で割ったあまり」の求め方を総特集! 〜 逆元から離散対数まで 〜

追記

  • フェルマーの小定理はmodの法が素数のときに使える.10^9+7素数
  • 繰り返し2乗法は上のバッチを組む方法と似ているが,x^(2^i)を下から順番に計算していって,順次modを取ってるので,modの法を越えてもオーバーフローしないのがポイントだね.
  • 蟻本のP.114に繰り返し2乗法が,P.260辺りにフェルマーの小定理とかのことが書いてあった.フェルマーの小定理はmodの法が素数でないときの拡張もあるらしい(そういえば受験問題で見たことがある気がする).蟻本,ダイケストラ法の辺りで読むスピードが落ちてきてモチベが削られて中断してたので,やっぱりちゃんとやろうという気持ちになった.