🔫
FPS24 G - 硬貨 勉強メモ
問題リンク
問題概要
円硬貨、 m 円硬貨、 m + 1 、 \cdots 円硬貨を自由に使いちょうど m + L - 1 円支払う方法の個数を N で割った余りを求めてください。 998244353
ただし、つの支払い方は、払う枚数が 2 つの支払い方で異なる効果が存在するときに区別します。 2
制約
- 入力される値はすべて整数
1 \leq N, M, L \leq 5000
解説
となります。(等比級数の和の公式を思い出すと良いです。)
よって、
なるべき級数
この値は以下のように差分更新をすることで、
また、これは掛け算・割り算の筆算の要領でやることで、各計算は
(昇べきの順に係数を合わせるようなイメージで実装すると良いです。)
実装例(Python3)
Fps = list[int]
MOD = 998244353
def div(f: Fps, d: int) -> Fps:
n = len(f)
res = [0] * n
for i in range(n):
res[i] = f[i]
if i + d < n:
f[i + d] = (f[i + d] + res[i]) % MOD
return res
def mul(f: Fps, d: int) -> Fps:
n = len(f)
res = [0] * n
for i in range(n):
res[i] = (res[i] + f[i]) % MOD
if i + d < n:
res[i + d] = (res[i + d] - f[i]) % MOD
return res
N, M, L = [int(s) for s in input().split()]
f = [0] * (N + 1)
f[0] = 1
for i in range(1, L + 1):
f = div(f, i)
for m in range(1, M - L + 2):
print(f[N])
f = mul(div(f, m + L), m)
所感
畳み込みと FPS inv を使うと TLE をして難しかった…。と思ったら
Discussion