Description
我们有n个相同的弹珠,k个相同的盒子。现在随机的将每个弹珠扔进盒子中,使得最终每个盒子非空,求出一共有多少种不同的方案。两种方案不同当且仅当将盒子中的弹珠数最小表示后不同。由于方案数可能非常多,出题人又良心的不让你们写高精度,把答案摸998244353输出即可。
Input
第一行输入两个正整数n,k。
Output
输出共一行,一个整数表示Ans mod 998244353的值
Solution
以下皆为100分方法,皆可AC。
方法一:
类似第二类????????????????????????????????数的,我们将方案分成两种:
1.至少包含一个 1 的;
2.一个 1 都不包含。
设????[????][????]表示答案,那么表示1.的答案即为????[???? − 1][???? − 1],
表示2.的答案 即为????[???? − ????][????](相当于把每个数都加上1),
所以有: ????[????][????] = ????[???? − 1][???? − 1] + ????[???? − ????][????],时间O(????????)。
方法二:
如图:
可找到规律,设n=0,k=1是结果为1,
则第n行第k列=第(n-k)行第一列到第k列的和。
代码
方法一:
1 const 2 mo=998244353; 3 var 4 n,k:longint; 5 f:array [0..5001,0..5001] of longint; 6 function min(o,p:longint):longint; 7 begin 8 if o<p then exit(o); 9 exit(p); 10 end; 11 12 procedure main; 13 var 14 i,j:longint; 15 begin 16 f[0,0]:=1; 17 for i:=1 to n do 18 for j:=1 to min(i,k) do 19 f[i,j]:=(f[i-1,j-1]+f[i-j,j]) mod mo; 20 end; 21 22 begin 23 readln(n,k); 24 main; 25 writeln(f[n,k]); 26 end.
方法二:
const mo=998244353; var n,k:longint; sum:array [0..5001] of longint; f:array [0..5001,0..5001] of longint; procedure main; var i,j:longint; begin for i:=0 to 5000 do begin f[i,1]:=1; sum[i]:=1; end; for i:=2 to 5000 do begin for j:=i to 5000 do f[j,i]:=(sum[j-i]+f[j-i,i]) mod mo; for j:=i to 5000 do sum[j]:=(sum[j]+f[j,i]) mod mo; end; end; begin readln(n,k); main; writeln(f[n,k]); end.