全国信息学分区联赛模拟试题(三)_____解题报告

来源:互联网 发布:软件测试面试 编辑:程序博客网 时间:2024/06/06 04:38

1.中位数

思路:我们可以很简单的想到两层循环递推的做法,可是数据较大,无法循环。我们只能另找通路。

            10^6可以被一层循环完美的解决,所以我们从这方面入手。

             我们可以预处理!

            (1)找到中位数的位置

              (2)从中位数向两边扩展

              (3)统计大于其的个数,计入桶中

               (4)搜桶,据乘法原理可知,所有互为相反数的桶中数的乘积之和即为答案。

参考程序:

var
  n,ans,b,i,p,k:longint;
  a,x,y:array[-100001..100001]of longint;
begin
  assign(input,'median.in');reset(input);
  assign(output,'median.out');rewrite(output);
  readln(n,b);
  for i:=1 to n do
   begin
     read(a[i]);
     if a[i]=b then p:=i;
   end;
  x[0]:=1;y[0]:=1;
  for i:=p-1 downto 1 do
   begin
     if a[i]>b then k:=k+1 else k:=k-1;
     x[k]:=x[k]+1;
   end;
  k:=0;
  for i:=p+1 to n do
   begin
     if a[i]>b then k:=k+1 else k:=k-1;
     y[k]:=y[k]+1;
   end;
  for i:=-n to n do
   ans:=ans+x[i]*y[-i];
  write(ans);
  close(input);close(output);
end.



2.敲砖

思路:动态规划。很明显以行来动归是行不通了,我们从列入手。

参考程序:

var
  n,m,i,j,k,l,max:longint;
  f:array[0..60,0..510,0..60]of longint;
  a,s:array[0..60,0..60]of longint;
  x:array[0..60]of longint;
begin
  assign(input,'brike.in');reset(input);
  assign(output,'brike.out');rewrite(output);
  readln(n,m);
  for i:=1 to n do
   for j:=1 to n-i+1 do
    begin
      read(a[i,j]);
      s[j,i]:=s[j,i-1]+a[i,j];
    end;
  for i:=1 to n do x[i]:=x[i-1]+i;
  f[n+1,0,0]:=0;
  for i:=n downto 1 do
   for j:=0 to n-i+1 do
    for k:=j-1 to n-i do
     for l:=j+x[k] to m do
      if f[i,l,j]<f[i+1,l-j,k]+s[i,j] then
       f[i,l,j]:=f[i+1,l-j,k]+s[i,j];
  for i:=1 to n do
   for j:=0 to n-i+1 do
    if f[i,m,j]>max then max:=f[i,m,j];
  write(max);
  close(input);close(output);
end.


4.单词

思路:有陷阱,太简单,直接见程序。

参考程序:

var
  x:array[0..110000]of string;
  m,i,n:longint;
  t:string;
procedure kp(l,r:longint);
var
  i,j:longint;
  t,a:string;
begin
  i:=l;j:=r;a:=x[random(r-l+1)+l];
  repeat
    while x[i]<a do i:=i+1;
    while x[j]>a do j:=j-1;
    if i<=j then
     begin
       t:=x[i];x[i]:=x[j];x[j]:=t;
       i:=i+1;j:=j-1;
     end;
  until i>j;
  if i<r then kp(i,r);
  if j>l then kp(l,j);
end;
begin
  assign(input,'words.in');reset(input);
  assign(output,'words.out');rewrite(output);
  randomize;
  readln(n);
  for i:=1 to n do
   readln(x[i]);
  readln(t);
  for i:=1 to n do
   if pos(t,x[i])=1 then
    begin m:=m+1;x[m]:=x[i];end;
  kp(1,m);
  for i:=1 to m do
   writeln(x[i]);
  close(input);close(output);
end.

4.邮递员

思路:正反向两次spfa

参考程序:

var
  n,m,i,oo,x,y,z,head,ans,t,tail,j:longint;
  dis,q:array[0..1100]of longint;
  map,tt:array[0..1100,0..1100]of longint;
  inq:array[0..1100]of boolean;
procedure spfa;
var
  head,tail:longint;
begin
  fillchar(inq,sizeof(inq),0);
  fillchar(dis,sizeof(dis),$7f shr 2);
  head:=0;tail:=1;
  dis[1]:=0;inq[1]:=true;q[1]:=1;
  while head<>tail do
   begin
     head:=head mod n+1;
     i:=q[head];
     inq[i]:=false;
     for j:=1 to n do
      if dis[i]+map[i,j]<dis[j] then
       begin
         dis[j]:=dis[i]+map[i,j];
         if not inq[j] then
          begin
            tail:=tail mod n+1;
            inq[j]:=true;
            q[tail]:=j;
          end;
       end;
   end;
  for i:=1 to n do ans:=ans+dis[i];
end;
begin
  assign(input,'post.in');reset(input);
  assign(output,'post.out');rewrite(output);
  readln(n,m);
  fillchar(map,sizeof(map),$7f shr 2);tt:=map;
  oo:=map[0,0];
  for i:=1 to m do
   begin
     readln(x,y,z);
     if z<map[x,y] then map[x,y]:=z;
     if z<tt[y,x] then tt[y,x]:=z;
   end;
  spfa;map:=tt;spfa;
  write(ans);
  close(input);close(output);
end.


1 0