jzoj C组 2017.1.19 比赛

第一题——小x的游戏

题目描述

   Tac游戏在一个4*4的方格上进行。起先可能会在16个方格中出现一个标记‘T’,其余的方格是空着的。

   游戏有两个玩家,小x和小o。小x先开始,然后游戏轮流进行。每一步玩家可以将他的标记放入一个空的方格中。小x的标记是‘X’,小o的标记是‘O’。

   在一个玩家结束操作后,如果出现一行、一列或者对角线都是该玩家的标记,或者有3个该玩家的标记以及标记‘T’,那么他获得胜利,游戏结束,否则游戏继续,进入另一个玩家的回合。如果所有的方格都被填满,并且没人获得胜利,那么游戏结束,为平局。

   给出一个4*4的方格,包括‘X’,‘O’,‘T’和‘.’(‘.’表示空的方格),输出现在游戏的状态,游戏的状态包括:

   • “X won”(游戏结束,小x获胜)

   • “O won”(游戏结束,小o获胜)

   • “Draw”(游戏结束,平局)

   • “Game has not completed”(游戏还未结束)

   如果有空格,并且游戏还未结束,你应该打印 “Game has not completed”,即使最后的结果是一定的。

输入

第一行一个整数T,表示测试数据的组数。

每组测试数据包括4行,每行4个字符,如题所述。每组测试数据后会有一行空行。

输出

对于每组测试数据,输出“Case #x: y”,x表示第x组测试数据(组号从1开始),y即上述的状态之一。注意‘O’不是‘0’。

样例输入

6

XXXT

….

OO..

….

XOXT

XXOO

OXOX

XXOO

XOX.

OX..

….

….

OOXX

OXXX

OX.T

O..O

XXXO

..O.

.O..

T…

OXXX

XO..

..O.

…O

样例输出

Case #1: X won

Case #2: Draw

Case #3: Game has not completed

Case #4: O won

Case #5: O won

Case #6: O won

数据范围限制

对于50%的数据:1<=T<=10

对于100%的数据:1<=T<=110


每行每列每个对角线都搜一次,如果有满足获胜的方法,就输出。如果没人获胜,就判断这里有没有空格。有就输出Game has  not completed 没有则输出Draw。

代码如下:

var  n,i,j,k,l:longint;
     w:boolean;
     a:array[1..4,1..4]of char;
     b:array['A'..'Z']of longint;

procedure pdd2(x:longint);
var   i:longint;
begin
  for i:=1 to 4 do if a[i,x-i+1]='.' then exit else inc(b[a[i,x-i+1]]);
  if b['X']=4 then begin l:=1; writeln('X won'); exit; end;
  if b['O']=4 then begin l:=2; writeln('O won'); exit; end;
  if (b['X']=3)and(b['T']=1) then begin l:=1; writeln('X won'); exit; end;
  if (b['O']=3)and(b['T']=1) then begin l:=2; writeln('O won'); exit; end;
end;

procedure pdd1(x:longint);
var   i:longint;
begin
  for i:=1 to 4 do if a[i,x+i-1]='.' then exit else inc(b[a[i,x+i-1]]);
  if b['X']=4 then begin l:=1; writeln('X won'); exit; end;
  if b['O']=4 then begin l:=2; writeln('O won'); exit; end;
  if (b['X']=3)and(b['T']=1) then begin l:=1; writeln('X won'); exit; end;
  if (b['O']=3)and(b['T']=1) then begin l:=2; writeln('O won'); exit; end;
end;

procedure pdl(x:longint);
var   i:longint;
begin
  for i:=1 to 4 do if a[i,x]='.' then exit else inc(b[a[i,x]]);
  if b['X']=4 then begin l:=1; writeln('X won'); exit; end;
  if b['O']=4 then begin l:=2; writeln('O won'); exit; end;
  if (b['X']=3)and(b['T']=1) then begin l:=1; writeln('X won'); exit; end;
  if (b['O']=3)and(b['T']=1) then begin l:=2; writeln('O won'); exit; end;
end;

procedure pdh(x:longint);
var   i:longint;
begin
  for i:=1 to 4 do if a[x,i]='.' then exit else inc(b[a[x,i]]);
  if b['X']=4 then begin l:=1; writeln('X won'); exit; end;
  if b['O']=4 then begin l:=2; writeln('O won'); exit; end;
  if (b['X']=3)and(b['T']=1) then begin l:=1; writeln('X won'); exit; end;
  if (b['O']=3)and(b['T']=1) then begin l:=2; writeln('O won'); exit; end;
end;

begin
  assign(input,'game.in');
  assign(output,'game.out');
  reset(input);
  rewrite(output);
  readln(n);
  for i:=1 to n do
    begin
      l:=0;
      w:=false;
      for j:=1 to 4 do
        begin
          for k:=1 to 4 do
            begin
              read(a[j,k]);
              if a[j,k]='.' then w:=true;
            end;
          readln;
        end;
      readln;
      write('Case #',i,': ');
      for j:=1 to 4 do
        begin
          fillchar(b,sizeof(b),#0);
          pdh(j);
          if l<>0 then break;
        end;
      if l<>0 then continue;
      for j:=1 to 4 do
        begin
          fillchar(b,sizeof(b),#0);
          pdl(j);
          if l<>0 then break;
        end;
      if l<>0 then continue;
      fillchar(b,sizeof(b),#0);
      pdd1(1);
      if l<>0 then continue;
      fillchar(b,sizeof(b),#0);
      pdd2(4);
      if l<>0 then continue;
      fillchar(b,sizeof(b),#0);
      if w=true then writeln('Game has not completed') else writeln('Draw');
    end;
  close(input);
  close(output);
end.

第二题——小x的三角形

题目描述

   小x和小o在一起研究各种图形的性质。小x发明了一个问题:一个完全无向图有n个顶点,选择m条边得到它们,并将剩余的n*(n-1)div 2-m条边给小o。

   小x和小o喜欢图中的三角形,他们想知道他们得到的边所形成的图共形成了多少个三角形。

   图的顶点从1到n编号。

输入

   第一行包含两个用空格隔开的整数n和m,分别表示顶点数和小x选取的边数。

   接下来m行每行两个整数ai,bi,表示小x选取的第i条边连接顶点ai,bi,数据保证小x得到的图和初始的完全图无重边和自环。

输出

输出一行一个整数,小x和小o得到的图所包含三角形的总数。

样例输入

input1:

5 5

1 2

1 3

2 3

2 4

3 4

input2:

5 3

1 2

2 3

1 3

样例输出

output1:

3

output2:

4

数据范围限制

【数据范围】

对于20%的数据 1<=n<=20

对于60%的数据 1<=n<=100

对于100%的数据 1<=n<=20000, 0<=m<=10^6,m<=n(n-1)/2,1<=ai,bi<=n,ai≠bi

提示

【样例解释】

第一个样例,小x得到的图有两个三角形:(1,2,3)和(2,3,4),小o有一个三角形(1,4,5),所以总数是3。

第二个样例,小x的图只有一个三角形(1,2,3),小o的图有3个三角形(1,4,5),(2,4,5)和(3,4,5),所以总数是4。


公式为:C(3,n)-(每个点与点联通和不连通的乘积) div 2


代码如下:

var   t,i,n,j,z,m:longint;
      x,s:int64; 
      a:array[1..20000]of longint;
begin
  assign(input,'triangles.in');
  assign(output,'triangles.out');
  reset(input);
  rewrite(output);
  readln(m,n);
  for j:=1 to n do
    begin
      readln(x,z);
      a[x]:=a[x]+1;
      a[z]:=a[z]+1;
    end;
  x:=m*(m-1)*(m-2) div 6;
  s:=0;
  for j:=1 to m do inc(s,a[j]*(m-1-a[j]));
  s:=s div 2;
  x:=x-s;
  writeln(x);
  close(input);
  close(output);
end.

第三题——eko

题目描述

     小x最近终于不用干搬砖的活了,他成为了一名光荣的伐木工人。但伐木工人也不好当,他每天必须至少砍下M米的木材。但小x对此感到毫无压力,因为小y最近给他买了一台崭新的伐木机,可以像野火一样将森林摧毁。但这台伐木机实在太大了,它一次只能将一整排树木一起砍倒。

     伐木机是这样工作的:小x设计一个参数H,然后伐木机将一排N个树木砍倒,然后得到每棵树高于H的部分。比如,有4棵树,高度分别为20,15,10,17米,而小x将H设为了15米。这样,他从第一棵得到了5m的木材,第四棵得到了2m的木材,一共是7m。当然,如果一棵树的高度不大于H,那么就不会被砍倒,也就不会留下木材。小x是个环保主义者,他希望H尽可能大,这样他砍倒的树木可以尽可能少。当然,前提是小x能至少得到M米木材。

输入

第一行两个整数N,M,代表有N棵树,小x每天至少砍M米木材。

第二行N个整数Ai,代表每棵树的高度。

输出

一行一个整数,代表所要求的最大高度。

样例输入

4 7

20 15 10 17

样例输出

15

数据范围限制

对于30%的数据:1 ≤ N ≤1 000

对于100%的数据:

1 ≤ N ≤1 000 000

1 ≤ M ≤ 2 000 000 000

1 ≤ Ai ≤ 1 000 000 000


二分答案,求出最高的高度为r,进行二分。


代码如下:

var i,l,r,k,n,m,x,mid:longint;
    ans,nmax:int64;
    a:array[0..1000000] of longint;

function max(x,y:longint):longint;
begin
  if x>y then exit(x) else exit(y);
end;

begin
  assign(input,'eko.in');
  assign(output,'eko.out');
  reset(input);
  rewrite(output);
  readln(n,m);
  for i:=1 to n do
    begin
      read(a[i]);
      r:=max(a[i],r);
    end;
  l:=1;
  while l<=r do
    begin
      mid:=(r+l) div 2;
      for i:=1 to n do if a[i]>mid then inc(nmax,a[i]-mid);
      if nmax>=m then
        begin
          ans:=mid;
          l:=mid+1;
        end
      else r:=mid-1;
      nmax:=0;
    end;
  writeln(ans);
  close(input);
  close(output);
end.

第四题——math

题目描述

 小x正在做他的数学作业,可是作业实在太难了。题目是这样的:

1.给定一个含有N个数的数列V。

2.你可以从数列中恰好移除K个数,定义移除后的数列为V’。

3.定义M为V’中任意两个数的差的最大值,m为V’中任意两个数的差的最小值。

4.请你选择删去的K个数,使得M+m最小。

 小x的数学十分之差,于是他只能向你求助了。

输入

第一行两个整数N和K。

第二行N个整数Vi。

输出

一行一个整数,为最小的M+m的和。

样例输入

5 2

-3 -2 3 8 6

样例输出

7

数据范围限制

对于60%的数据:3 ≤ N ≤ 2 000

对于100%的数据:

3 ≤ N ≤ 200 000

1 ≤ K ≤ N - 2

-5 000 000 ≤Vi ≤ 5 000 000

提示

【样例解释】

删去-3和-2,得到V’={3,6,8},M=5,m=2,M+m=7。


现将n个数进行快排,因为只能从前和后面删数,枚举前面删数的个数,求出删这几个数,的差的最小值加差的最大值。


代码如下:

var  n,k,i,z,j,min,max,l:longint;
     a,b:array[0..200000]of longint;

procedure qsort(l,r:longint);
var  i,j,mid:longint;
begin
  if l>r then exit;
  i:=l; j:=r; mid:=a[(i+j) div 2];
  repeat
    while a[i]<mid do inc(i);
    while a[j]>mid do dec(j);
    if i<=j then
      begin
        a[0]:=a[i]; a[i]:=a[j]; a[j]:=a[0];
        inc(i);
        dec(j);
      end;
  until i>j;
  qsort(l,j);
  qsort(i,r);
end;

begin
  assign(input,'math.in');
  assign(output,'math.out');
  reset(input);
  rewrite(output);
  readln(n,k);
  for i:=1 to n do read(a[i]);
  qsort(1,n);
  for i:=1 to n-1 do b[i]:=a[i+1]-a[i];
  min:=maxlongint;
  for i:=1 to k+1 do
    begin
      z:=n-k+i-1;
      if l<i then
        begin
          max:=maxlongint;
          for j:=i to z-1 do
            if b[j]<max then
              begin
                l:=j;
                max:=b[j];
              end;
        end
      else
        if b[z-1]<b[l] then l:=z-1;
      if b[l]+a[z]-a[i]<min then min:=b[l]+a[z]-a[i];
    end;
  write(min);
  close(input);
  close(output);
end.

由于今天的题比较水,早AK早写博客。

原文地址:https://www.cnblogs.com/Comfortable/p/8412443.html