https://atcoder.jp/contests/abc167/tasks/abc167_e
解説
https://atcoder.jp/contests/abc167/submissions/13094693
まず、素数mod上での四則演算とコンビネーションが計算できるようにしよう。
二項係数 mod 素数を高速に計算する方法 [累積和, フェルマーの小定理, 繰り返し二乗法, コンビネーション, 109+7] - はまやんはまやんはまやん
このライブラリがあることがACの必要条件。
どこから数え上げようかと思うところであるが、何かを固定することで計算しやすくなる部分が無いか探す。
問題を見ると、固定する部分の候補として「隣り合うブロックで同色である部分の個数」がある。
この個数をk個としておく。
すると、k=0,1,...,Kの場合の組合せの総和を取れば答えになる。
少しシンプルになった。
隣り合うブロックの組であって、同じ色で塗られている組がk個であるとする。
ここからちょっと飛躍が必要なのだが、隣り合うブロック部分はN-1個あるが、
そのN-1個のうち、どこにk個等しくなる部分があるかを考える。
これはC(N-1, k)通りある。
そして、実は、その全ての組について色の塗り方は等しくなり、M×(M-1)N-1-k通りとなる。
分かりやすさのために、N-1個のうち最初のk個が同色になっていると考えよう。
すると、1番目はM色の選択ができ、そこから次のk個は色が同じである必要があるため、1通り、
それ以降は、前のブロックとは違う色にする必要があるので、M-1通りとなる。
よって、(1番目)×(同じにする)×(異なるようにする)で、M×1K×(M-1)N-1-kであり、M×(M-1)N-1-kとなる。
これが、最初のk個が同色以外のパターンでも考えてみると、前のブロックと同じにする回数と
前のブロックと異なるようにする回数は同じになるため、結局M×(M-1)N-1-kとなる。
よって、各kについて、C(N-1, k)×M×(M-1)N-1-kとなり、これの総和を取ると答えになる。
自分の解法では、なんとなくN-1,M-1があるので、N=1とM=1の時は念のため場合分けしている。
もしかしたら、いらないかも。
int N, M, K; Comb<mint, 1010101> com; //--------------------------------------------------------------------------------------------------- void _main() { cin >> N >> M >> K; if (N == 1) { cout << M << endl; return; } if (M == 1) { if (N - 1 == K) cout << M << endl; else cout << 0 << endl; return; } mint ans = 0; rep(k, 0, K + 1) ans += com.aCb(N - 1, k) * M * (mint(M - 1) ^ (N - 1 - k)); cout << ans << endl; }