結果
| 問題 |
No.1191 数え上げを愛したい(数列編)
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2021-06-18 11:13:16 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
AC
|
| 実行時間 | 159 ms / 2,000 ms |
| コード長 | 2,659 bytes |
| コンパイル時間 | 226 ms |
| コンパイル使用メモリ | 82,320 KB |
| 実行使用メモリ | 155,592 KB |
| 最終ジャッジ日時 | 2024-06-22 01:20:23 |
| 合計ジャッジ時間 | 3,479 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 26 |
ソースコード
def main0(n,m,a,b):
mod=998244353
dp=[0]*(b+1)
dp[0]=1
for _ in range(n-1):
ndp=[0]*(b+1)
for i in range(b+1):
for j in range(a,b+1):
if i+j>b:continue
ndp[i+j]+=dp[i]
ndp[i+j]%=mod
dp=ndp
ans=0
for i in range(1,m+1):
# 初項がiの場合、最終項はi+bまでOK
# これがm以下ならsum(dp)
# mを超えたらsum(dp[:-(i+b-m)])
if i+b<=m:
ans+=sum(dp)%mod
else:
ans+=sum(dp[:-(i+b-m)])%mod
for i in range(1,n+1):
ans=ans*i%mod
return ans
# 任意の二項の差の絶対値はa以上b以下
# 最大最小の差がb以下で、昇順に並べたときの値の間隔はa以上b以下
# 初項0として、最終項はa*(n-1)以上b以下。なのでa*(n-1)<=bでないなら0
# 初項0で末項がxとする。1回の操作ではA~Bを加算でき、n-1回の操作で合計xが加算された。
# A*(N-1)<=x<=B
# <=> 初項0で末項がxとする。1回の操作では0~B-Aを加算でき、n-1回の操作で合計xが加算された。
# 0<=x<=B-A*(N-1)
# i回目の操作でyiを加算する(0<=yi<=B-A) ... yi<=B-Aの条件はsum(yi)<=B-A*(N-1)の条件から自然と満たすので明示的に考える必要はない。
# x個のボールをn-1個のグループに分ける。
# <=> x個のボールを並べてn-2個区切りを入れる入れ方、cmb(x+1+n-2-1,n-2)
# 区切り入る箇所がx+1,区切りの個数がn-2
def main1(n,m,a,b):
if a*(n-1)>b:return 0
mod=998244353
def cmb(n,r,mod=mod):
if (r<0 or r>n):
return 0
r=min(r,n-r)
return (g1[n]*g2[r]*g2[n-r])%mod
g1=[1,1] # g1[i]=i! % mod :階乗
g2=[1,1] # g2[i]=(i!)^(-1) % mod :階乗の逆元
inverse=[0,1]
for i in range(2,n+m+1):
g1.append((g1[-1]*i)%mod)
inverse.append((-inverse[mod%i]*(mod//i))%mod)
g2.append((g2[-1]*inverse[-1])%mod)
dp=[0]*(b-a*(n-1)+1)
# dp[x]:初項0末項xとなる数列の個数。x個のボールをn-1個に分ける分け方。
# 横に並んだx個のボールがある。区切りを入れられる箇所がx+1個ある。重複を許しn-2個の区切りを入れる。
for x in range(b-a*(n-1)+1):
dp[x]=cmb(x+1+n-2-1,n-2)
sdp=[0]
# sdp[x+1]:初項0末項x以下となる数列の個数
for x in dp:sdp.append(sdp[-1]+x)
ans=0
for y in range(1,m-a*(n-1)+1):
# 初項y 最小末項y+a*(n-1) 最大末項min(y+b,m)
t=min(y+b,m) - (y+a*(n-1))
ans+=sdp[t+1]
ans%=mod
for i in range(1,n+1):
ans=ans*i%mod
return ans
if __name__=='__main__':
n,m,a,b=map(int,input().split())
ret1=main1(n,m,a,b)
#ret0=main0(n,m,a,b)
print(ret1)
#print(ret0)