めちゃくちゃ計算した.こんなんどうやったら時間内に解けるんだろう? クエリの読み替えが本質だったっぽくて,これに気付くことが出来ればあるいは...?みたいな感じかもしれない.ただ,今の自分では厳しい...
問題
解法
以降,操作対象の数列を とし,0-indexed とする.
列全体の動作を考えるのは難しいので,数列の添え字 を固定して要素 1 つ 1 つに注目する.クエリの範囲は全部で 通りあるが,このうち が範囲内に含まれるのは かつ のときで,即ち 通り.これらの数を毎回書くと大変なので,, とおいておく.
解法 (泥臭いので読み飛ばしてもらってもよいです)
現在の の値を持てば DP が出来そうなので,DP テーブルを次のように定義してみる.
に関して,全ての に対して である.
個目のクエリが ,, である場合のそれぞれについて, への遷移を考える (集める DP).
クエリ
がクエリの範囲内であるかどうかで更に場合分けをする.
が範囲内の場合
が範囲内となるような範囲の選び方は 通りである.
クエリにおいて となるのは,
- クエリの前は で, のクエリが飛んでくる場合
- クエリの前は で, のクエリが飛んでくる場合
の 2 つのケースが考えられる.従って,このケースの寄与は次の式 で表される.
が範囲外の場合
が範囲内となるような範囲の選び方は 通りである.
が範囲外の場合は元から である必要があり, の値は関係ない.従って,このケースの寄与は次の式 で表される.
クエリ
がクエリの範囲内であるかどうかで更に場合分けをする.
が範囲内の場合
が範囲内となるような範囲の選び方は 通りである.
クエリにおいて となるのは,
- クエリの前は で, のクエリが飛んでくる場合
- クエリの前は で, のクエリが飛んでくる場合
の 2 つのケースが考えられる.従って,このケースの寄与は次の式 で表される.
が範囲外の場合
クエリにおいて が範囲外の場合と全く同様であり,このケースの寄与は次の式 で表される.
クエリ
まず, クエリにおいて の値は変化しないので,任意の範囲に対して からの寄与があり, () からの寄与はない.従って, この場合の寄与は式 で表される.
また, クエリにおいてはクエリ自体による寄与が存在する. が範囲内である必要があるので,これは以下のように書ける.
ここで, が分からないので別で求める必要がある.
取り敢えずこの値を とおけば,クエリ自体の寄与は次の式 で表される.
以上 より, の表示は式 のようになる.
そして,この問題で求めたいのは を について和をとったものなので, を次のように定義する.
式 の両辺を について和をとって,式 を得る.
良い感じになってきたが, が分からないのでこれ以上は計算が進まない.そこで,以下は を求める.
まず, は定義より次のようになる.
そして, も とほぼ同様の漸化式を立てることが出来る.導出過程は省略し,結果を式 に示す.式 との違いは最終項の有無のみである.
ここで, の総和は実は問題文にその答えが書かれており,
である (もちろん普通に求めてもよい).従って,更に式 の計算を進めることができ,
となる.これは以下のようにして について独立に解くことができる.
さて, の具体的な表示が得られたので式 に代入する.
この形の漸化式は両辺を で割ると解けて,
となる.式 より,求める答えは である.
ここで,
である.適切に計算すれば, は で求めることが出来る.
これだと道のりがかなり長く,あまり綺麗ではありません.そこで,クエリの解釈の仕方を変えてみます.
のとき, によって となるのは, のときです.一方, によって となるのは, のときです.そして,その他の場合では は変化しません ( のケースは都合のいいように解釈をしてもよいです).ここで重要なのは, の値によらず, へと変化するのが 通りずつあり,何も変化しないのが 通りあるということです.
つまり, および をひとまとめにして考えると,これらは次の 2 つの操作に置き換えられます.
- : へと更新する
- : 何もしない
ここまで来れば, 回の操作後に となる場合の数 を一発で求められます.まず, が クエリの対象となるのは 通りです.また,クエリのパターン数は 通りだったので, クエリの対象とならないのは 通りということになります.
従って, 回の操作において一回も クエリの対象とならないのは 通りです.このとき,操作後の の値は です.
そして, 回の操作において一回以上 クエリの対象となるのは 通りです.このとき,操作後に となる場合の数は によりません.つまり, となる場合の数は 通りです.
以上より, は以下のように求められ,これは上で示した結果と一致しています.
そして,任意の 回の操作における クエリの出力の総和 に関する漸化式 :
に代入すると解ける形になるので,解いて を計算すれば AC が取れます (代入と漸化式の計算パートは折り畳み部分に書いています).
実装 (Python)
P = 998244353 N, M, Q = map(int, input().split()) inv_2 = pow(2, -1, P) C = (N + 1) * N * inv_2 % P I = [(t + 1) * (N - t) % P for t in range(N)] a = (2 * M + 1) * C % P b = [M * I[t] % P for t in range(N)] ans = 0 for t in range(N): v1 = I[t] * (M - 1) % P * inv_2 % P u1 = Q * pow(a, Q - 1, P) % P u2 = (pow(a - b[t], Q, P) - pow(a, Q, P)) * pow(b[t], -1, P) % P ans += v1 * (u1 + u2) % P print(ans % P)