これ解くのに1時間はかかりすぎた。反省回。
atcoder.jp
問題概要
個の整数からなる集合
と整数
が与えられる。
この集合に含まれる1つの整数
を取り除き、整数
を
mod
に書き換える。この操作を集合
が空になるまでの
回行う。
集合の整数を取り除く順序は
通り存在するが、全ての順序における最終的な整数
の値の総和を
で割った余りで求めよ。
制約
- 集合の整数:
(
は相異なる)
解法
dpをする。
集合の個の整数を
とする。
まず、となる
について、
を後回しにして先に
を使った場合、mod
によって整数
は変化しない。
また、mod は必ず適用されるため、最終的な整数
は
を満たす。
ここで、各について、
回の操作後に最終的に
となる通り数を求めることを考える。
そこで以下のdpを考える。
=
を使った(もしくは後回しにした)時点で整数
が
の時の通り数
初期値は とする。
dpはから順に以下のように伝搬し、各通り数の和を求める。
を後回しにする場合 (つまり、整数
に何も影響しないケース)
を適用する場合 (整数
に影響を与えうるケース)
- (もしくは
について
)
個の要素
を使う順序で並べることを考えた時、
(1)の は以下のイメージの青い箇所の
通りである。(2)は赤い箇所の1通りに該当する。

(i+1個の要素の中でを最初に使うのが1通り、それ以外がi通り)
そして、最後に を計算して解とすればよい。
計算量 で求められる。
実装
提出コード(PyPy3): Submission #4778607 - ExaWizards 2019
N, X = map(int, input().split()) *V, = map(int, input().split()) MOD = 10**9 + 7 V.sort() S = [0]*(X+1) S[X] = 1 T = [0]*(X+1) zeros = [0]*(X+1) for i in range(N-1, -1, -1): T[:] = zeros for k in range(X+1): S[k] %= MOD T[k] += S[k] * i % MOD T[k % V[i]] += S[k] S, T = T, S print(sum(k*S[k] % MOD for k in range(V[0])) % MOD)