Official

F - Almost Sorted 2 Editorial by toam


\(A\) に含まれる \(v\) の個数を \(\mathrm{cnt}[v]\) とします.

条件から以下が成り立ちます.

  • \(B\) において,ある要素 \(v\) の直前に \(v+D\) より大きい要素は置くことができない

この考えをもとにして,値が小さい方から \(B\) の相対的な位置を決めていく 挿入 dp でこの問題を解きます.

\(v\) 未満の相対的な位置が決まっていたとします.このとき,\(v\) を挿入できる位置は,(現在の \(B\) に依らず)\(v-D\) 以上 \(v\) 未満の数の個数に依存しています.

例えば \(D=3, B=(4, 1, 3, 5, 4, 2, 3)\) で,\(v=6\) を挿入するとき,挿入できる場所は以下のようになります:

( 4,  1,  3,  5,  4,  2,  3,  )
 ^       ^   ^   ^       ^   ^

挿入できる箇所を数式で書くと \(\mathrm{cnt}[v-D]+\ldots+\mathrm{cnt}[v-1]+1\) 箇所です.(\(+1\) は末尾に追加できることを表しています.)

これらの挿入可能な位置から \(v\) を合計 \(\mathrm{cnt}[v]\) 個挿入する方法は,互いに区別できない \(\mathrm{cnt}[v]\) 個の玉を互いに区別できる \(\mathrm{cnt}[v-D]+\ldots+\mathrm{cnt}[v-1]+1\) 個の箱に入れる方法に等しく \(\dbinom{\mathrm{cnt}[v-D]+\ldots+\mathrm{cnt}[v]}{\mathrm{cnt}[v]}\) 通りです.

よって,求める答えは

\[\prod_{v=1}^{\max(A)}\dbinom{\mathrm{cnt}[v-D]+\ldots+\mathrm{cnt}[v]}{\mathrm{cnt}[v]}\]

です.これは \(O(N+\max(A))\) で計算できます.

mod = 998244353
table_size = 3 * 10**5

fac = [1] * (table_size + 1)
finv = [1] * (table_size + 1)

for i in range(2, table_size + 1):
    fac[i] = fac[i - 1] * i % mod
finv[table_size] = pow(fac[table_size], mod - 2, mod)
for i in range(table_size - 1, -1, -1):
    finv[i] = finv[i + 1] * (i + 1) % mod


def binom(n, k):
    if n < 0 or k < 0 or k > n:
        return 0
    return (fac[n] * finv[k] % mod) * finv[n - k] % mod


N, D = map(int, input().split())
A = list(map(int, input().split()))
cnt = [0] * (max(A) + 1)

for i in A:
    cnt[i] += 1

ans = 1
s = 0
for i in range(max(A) + 1):
    s += cnt[i]
    ans *= binom(s, cnt[i])
    ans %= mod
    if i >= D:
        s -= cnt[i - D]

print(ans)

posted:
last update: