5195. 【NOIP2017提高组模拟7.3】A (Standard IO)

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.

 

posted @ 2018-08-15 15:26  猪都哭了  阅读(343)  评论(0)    收藏  举报