スナネコです。yosupo judgeにある を解きました。
問題
d=0の時はただの等比数列の和です。
d=1の時を計算する問題もときどき見ますね。例えば「1の目が出るまでサイコロを振るときの回数の期待値は?」とかです。
…………冗談です。まさかこの問題でそんな計算しませんよね?
さて、dが大きなときでもやることはd=0,1の時と同じで、rを掛けて差を取っていきます。
例えばd=4のときは
という感じですね。
なんだか見たことのない数が残りました。こういうときはOEISです。
1,11,11,1 - OEIS
Eulerian Numberというらしいです。d=5の場合も計算すると一致したので多分あってるでしょう。
wikipediaを見てみます。
Eulerian number - Wikipedia
wikipediaに合わせて、Eulerian NumberをA(n,m)と表すことにしましょう。
スナネコは英語は読めませんが、数式を見れば大体の雰囲気はわかりますね。
A(n,m)を表す式は書いてありますが、nを固定したときに全部のmを高速に求める方法は書いてなさそうです。
このEulerian Numberを使って計算できればいいんですけど、うまくいきますかね。ちゃんと式に書いてみましょう。
愚直に計算するとO(d^2)です。困りました。
正解者の提出をちらっと見てみると、こういう式で計算してました。
スナネコの考えてる式と似たような感じなので、今の方針であってそうです。
二項係数の部分と、(…)^dの部分で変数を分離して、独立に累積和っぽく計算する工夫は面白いですね。これが使えないか試してみます。m+1-kをxと変数変換してみます。
うまくできましたね。これで、xのシグマについてはkが大きい方から累積和のように計算していくことができるので、高速に計算できるようになりました。
この計算式の通りにやっても全体でですが、逆元テーブルの線形構築や細かい計算を配列にメモしておくことでいくらか定数倍高速化が効きます。
これでAC……ではありません。d=0の時はそもそも最初のの時点で空和になって0になってしまいます。仕方がないのでこれだけ場合分けです。
ACは取れましたが、途中で紹介した他の正解者の計算式では場合分けをしてないみたいです。こっちも導出してみましょう。
最後の数式でd-kをyに変数変換します。
和を取る範囲が違いますね。ここが0から始まっているとd=0のときにも場合分けをしなくて済むようです。
wikipediaをよく見てみると、A(0,0)=1、n>0のときA(n,n)=0、と書いてありました。ということはそもそも一番最初の式の時点でm=dまで和を取ってよくて、そうすると整合性がありそうですね。
確かに同じ式が求まりました。