jzoj 模拟赛总结(2017.07.15)

T1.
iCow播放器:
FJ的iCow里存了N首曲子,按1..N依次编号。至于曲子播放的顺序,则是按一个Farmer John自己设计的算法来决定:  第i首曲子有一个初始权值R_i。当一首曲子播放完毕,接下来播放的将是所有曲子中权值最大的那首(如果有两首或多首曲子的权值相同,那么这些曲子中编号最小的那首会被选中)。 一首曲子在播放结束后,它的权值会被平均地分给其他N-1首曲子,它本身的权值清零。 如果一首曲子的权值无法被平均分配(也就是说,无法被N-1整除),那么被N-1除的余数部分将会以1为单位,顺次分配给排名靠前的曲子(也就是说,顺序为曲目1、曲目2…依次下去。当然,刚播放过的那首曲子需要被跳过),直到多出的部分被分配完。在选定的下一首曲子播放完毕后,这个算法再次被执行,调整曲子的权值,并选出再接下来播放的曲目。请你计算一下,按FJ的算法,最先播放的T 首曲子分别是哪些。

1 <= N <= 1,000
1 <= R_i <= 10,000
1 <= T <= 1000

题解:
我们观察数据可以发现,其实这题可以直接暴力,挺水的
照着题目要求打,每次找最大值中的序号最小的那个输出,然后用它影响其他其他N-1个点,注意 mod (n-1)后剩余的数。
时间复杂度:O(TN)

var
   a:array [0..1001] of longint;
   i,j,n,m,max,min:longint;
begin
    readln(n,m);
     for i:=1 to n do readln(a[i]);
     for i:=1 to m do
     begin
         max:=0; min:=0;
         for j:=1 to n do
           if a[j]>max
              then begin
                       max:=a[j];
                       min:=j;
                   end;
         writeln(min);
         for j:=1 to n do
              if min<>j  then
                 a[j]:=a[j]+(a[min] div (n-1));

         a[min]:=a[min] mod (n-1);
         j:=0;
         while a[min]<>0 do
         begin
              inc(j);
              if j<>min then
              begin
                        inc(a[j]);
                        dec(a[min]);
              end;
         end;
     end;
end.

T2.
山峰暸望:
一天,Bessie在眺望群山的时候,她产生了疑问:哪座山是最宽的捏?她用她新发明的山峰高度测量仪依次做N 次高度测量H_i 。一座山定义为一段连续的高度序列,序列中的高度一开始单调上升(或者不变),然后单调下降(或者不变)。举例来说,2, 3, 3, 5, 4, 4, 1这一段高度序列就是一座山。如果在她的视线范围内有一段只单调上升或者只单调下降的序列,也算是一座山。山的宽度定义为在这个山上进行的测量的次数(也就是序列的长度)。请帮Bessie找到最宽的山。

1 <= N <= 10,000
1 <= H_i <= 1,000,000,000

题解:
h_i后面这么多0,不存在的
我们可以发现,这题虽然看起来好像很难,单调前,单调后,其实不然,我们可以以每一个点为山峰去向2边扩展,然后比较找最大扩展长度。
时间复杂度:O(N^2)

var
    h:Array [0..10001] of longint;
    i,j,k,n,ans:longint;

function max(aa,bb:longint):longint;
begin
    if aa>bb then exit(aa);
    exit(bb);
end;

begin
    readln(n);
    for i:=1 to n do readln(h[i]);
    i:=1; ans:=0;
    for i:=0 to n do
    begin
         j:=i;
         k:=i;
         while (j>1) and (h[j-1]<=h[j]) do dec(j);
         while (k<n) and (h[k+1]<=h[k]) do inc(k);
         ans:=max(ans,k-j+1);
    end;
    writeln(ans);
end.

T3.
贝茜的晨练计划:
奶牛贝茜选择的运动方式是每天进行N分钟的晨跑。在每分钟的开始,贝茜会选择下一分钟是用来跑步还是休息。贝茜的体力限制了她跑步的距离,如果贝茜选择在第i分钟内跑步,她可以在这一分钟内跑D_i米,并且她的疲劳度会增加1。不过,无论何时贝茜的疲劳度都不能超过M。如果贝茜选择休息,那么她的疲劳度就会每分钟减少1,但她必须休息到疲劳度恢复到0为止。在疲劳度为0时休息的话,疲劳度不会再变动。晨跑开始时,贝茜的疲劳度为0。还有,在N分钟的锻炼结束时,贝茜的疲劳度也必须恢复到0。求贝茜最多能跑多少米。

1 <= N <= 10,000
1 <= D_i <= 1,000
1 <= M <= 500

题解:
我们发现这题其实可以就是一个DP:

f[i,j]表示前i分钟疲劳值为j的能跑的最大值。

然后初值
f[1,0]=0 第1分钟就开始休息
f[1,1]=d[1] 第1分钟就运动

然后
i从2 to n
对于每个枚举的i 我们的初值为
f[i,0]=f[i-1,0]
然后
j从1 to m 枚举疲劳值,也可以枚举到i,因为第i分钟疲劳值最多为i
①f[i,0]=max(f[i-j,j],f[i,0])
因为如果当前这一分钟疲劳值抵消掉了,然后疲劳值为j,因为他每分钟休息则抵消1点疲劳值且一旦休息必须等到疲劳值恢复为0,则他是从第i-j分钟有j疲劳值的情况而来。
②f[i,j]=f[i-1,j-1]+d[i]
因为当前这一分钟如果运动的话疲劳值就变成了j,则是由上一分钟i-1疲劳值为j-1而来,因为这一分钟运动而多了1点疲劳值,然后这一分钟运动了d[i],就加上d[i]。
为什么不用比较f[i-1,j]呢?
因为如果它到了这一步j没有改变的话就等于第i分钟没有进行运动,那么就是休息,这样的话他的疲劳值就要-1,就是由f[i-1,j+1]推来。
为什么也没有f[i-1,j+1]呢?
因为①的步骤已经处理出来了 //浪里个比

时间复杂度:O(NM)

var
    f:Array [0..10001,0..501] of longint;
    a:Array [0..10001] of longint;
    n,m,i,j:longint;

function min(aa,bb:longint):longint;
begin
   if aa>bb then exit(bb);
   exit(aa);
end;

begin
    readln(n,m);
    readln(a[1]);
    f[1,0]:=0; f[1,1]:=a[1];
    for i:=2 to n do
      begin
           readln(a[i]);
           f[i,0]:=f[i-1,0];
           for j:=1 to min(m,i) do
            begin
               if f[i-j,j]>f[i,0] then f[i,0]:=f[i-j,j];
               f[i,j]:=f[i-1,j-1]+a[i];
            end;
      end;
    writeln(f[n,0]);
end.

T4.
横幅:
Farmer John准备在牧场挂起一个”Welcome Home”的横幅迎接Bessie。横幅会挂在两个柱子间的长度介于L1..L2的金属丝上。牧场是一个W×H 的矩阵并且FJ在每个坐标点上都树立起了柱子,在这 (W + 1) * (H + 1)个柱子上,FJ要选两个连上金属丝以挂上横幅。 FJ不希望在横幅下面有别的柱子。 FJ需要你编程帮他算出有多少种挂横幅的可能。但是这个数据很大,也许32位整数都放不下。

1 <= L1 <= L2; L1 <= L2 <= 1,500
1 <= W <= 1,000 1 <= H <= 1,000

题解:
找规律+数学:
①我们手动推理发现,如果矩阵的长宽互质,那么它们的任意一条对角线都不经过其内的任意一个整数坐标点,即不经过柱子,所以我们可以枚举枚举矩形长i宽j的可能性,然后判断它们的gcd是否为1。
如果为1则
长宽互质,所以其对角线是不经过整数坐标点的,所以可能性+1,
然后乘上(w-i+1)*(h-j+1),因为在矩形中有这么多个这种小矩形,就有这么多的可能性
还要乘上2,因为矩形的对角线有2条

②因为上面仅仅只是处理了对角线,但是,我们要考虑!
l1=1的情况,因为任意2个柱子间距为1,这,也是一种情况!!!!
因此这时候我们还要给答案加上h*(w+1)+w*(h+1),因为有这么多个间距

时间复杂度:O((w+1)*(h+1))

var
    i,j,w,h:longint;
    k,l1,l2:real;
    ans:int64;

function gcd(aa,bb:longint):longint;
var
    x:longint;
begin
     if aa<bb then
     begin
           x:=aa; aa:=bb; bb:=x;
     end;
     x:=aa mod bb;
     while x>0 do
     begin
           aa:=bb;
           bb:=x;
           x:=aa mod bb;
     end;
     exit(bb);
end;

begin
     readln(w,h,l1,l2);
     for i:=1 to w+1 do
       for j:=1 to h+1 do
       if gcd(i,j)=1 then
       begin
             k:=sqrt(sqr(i)+sqr(j));
             if (k>=l1) and (k<=l2) then ans:=ans+(w-i+1)*(h-j+1)*2;
       end;
     if l1=1 then ans:=ans+w*(h+1)+h*(w+1);
     writeln(ans);
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值