1857. 最大值 (Standard IO)

Description

  找到一个数组的最大值的一种方法是从数组开头从前到后对数组进行扫描,令max=a0,如果a[i]>max,就更新max,这样就可以在O(N)的时间里找到一个数组的最大值。
  这个问题是相当简单的,但是想到了另一个问题,如果一个包含N个元素的数组a里面的元素的值是在1…K之间的整数,存在多少个不同的数组a,进行了如上扫描之后,max恰好进行了P次更新?
  下面是N = 4,K = 3,P = 2时所有情况
  1) {1,1,2,3}
  2) {1,2,1,3}
  3) {1,2,2,3}
  4) {1,2,3,1}
  5) {1,2,3,2}
  6) {1,2,3,3}
  共有6种情况
  由于答案可能很大,所以你仅仅需要把答案mod (10^9+7)输出。

Input

  输入文件findmax.in的第一行T,本题有T组数据。
  接下来T行,每行三个整数N,K,P

Output

  输出文件findmax.out包括T行,每行一个答案。

Sample Input

3

4 3 2

2 3 1

3 4 1

Sample Output

6

3

30

【数据规模】

30%数据 T=1;1 <= n <= 10;1 <= K <= 2;0 <= P < n
60%数据 T=1;1 <= n <= 50;1 <= K <= 10;0 <= P < n
100%数据1 <= T <= 100;1 <= n <= 100;1 <= K <= 300;0 <= P < n

题解:

  f[i,j,k]表示前i个用了j个数字有k次更新
  f[i,j,k]:=(f[i,j,k]+f[i-1,j,k]*j) mod 1000000007;
  //新加的数字小于等于前一个数字,不更新。
  f[i,j,k]:=(f[i,j,k]+s[i-1,j-1,k-1]) mod 1000000007;
  //新加的数字大于前一个数字,更新。
  s[i,j,k]:=(s[i,j,k]+f[i,j,k]+s[i,j-1,k])mod 1000000007;
  //s[i,j,k]表示之前a的所有的数。

代码:

const
  maxn=1000000007;
var
  f,s:array[0..100,0..300,0..100] of int64;
  a:array[0..100,1..3] of longint;
  x,y,z,n:longint;
function min(x,y:longint):longint;
begin
  if x<y then exit(x)
  else exit(y);
end;
function max(x,y:longint):longint;
begin
  if x>y then exit(x)
  else exit(y);
end;
var
  i,j,k:longint;
  ans:int64;
begin
  readln(n);
  for i:=1 to n do
    begin
      readln(a[i,1],a[i,2],a[i,3]);
      x:=max(x,a[i,1]);
      y:=max(y,a[i,2]);
      z:=max(z,a[i,3]);
    end;
  for i:=1 to y do
    begin
      f[1,i,0]:=1;
      s[1,i,0]:=i;
    end;
  for i:=2 to x do
    for j:=1 to y do
      for k:=0 to min(z,i-1) do
        begin
          f[i,j,k]:=(f[i,j,k]+f[i-1,j,k]*j) mod maxn;
          if k<>0 then
            f[i,j,k]:=(f[i,j,k]+s[i-1,j-1,k-1]) mod maxn;
          s[i,j,k]:=(s[i,j,k]+f[i,j,k]+s[i,j-1,k])mod maxn;
        end;
  for i:=1 to n do
    begin
      ans:=0;
      for j:=1 to a[i,2] do
        ans:=(ans+f[a[i,1],j,a[i,3]]) mod maxn;
      writeln(ans);
    end;
end.
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值