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