zoukankan      html  css  js  c++  java
  • jzoj C组 2017.1.13比赛

    第一题

    题目描述

    你玩过井字棋游戏吗?它的英文名字叫做tic-tac-toe,是一个古老的博弈游戏。游戏在一
    个3 £ 3的棋盘上进行。游戏约定,先在同一条线(横线、纵线或斜线)上占有3枚棋子者得
    胜。尽管现在借助计算机可以生成这个游戏所有可能的情况,但这个古老的游戏从未失去它
    在博弈游戏中的意义。在它的身上不断可以看到有新的东西产生。比如,有人将井字棋游戏
    从平面空间扩展到三维空间,发明了立体井字棋。立体井字棋的棋盘是一个n £ n £ n的立方
    体,游戏双方在立方体的这n3个格子中布子。与传统井字棋游戏的规则相似,首先占据了一
    条线上的全部n个格子的人获胜。当然,这个立方体的大小是有考究的,并不是所有的正整
    数n都合适: n小了获胜太易,先行者必胜; n大了获胜又太难,最后可能双方都无法获胜。
    为此,我们需要收集与该游戏有关的一些数据,以决定最佳的n的值。我们想知道,对于某
    个n,在游戏中有多少种获胜的情况。你的任务是确定,在n £ n £ n的立方体中放n个子,有
    多少种布子方案可以使这n个子连成一条线。

    输入

    输入数据为一个正整数n,表示立方体的大小。

    输出

    输出为一个正整数,它表示在n3的立方体中n个格子连成一条直线的方案数。

    样例输入

    2

    样例输出

    28

    数据范围限制

    对于30%的数据, n<=10;
    对于100%的数据, n <= 1000。


    找规律:3*n*n+4+6*n


    代码如下:

    var  n:longint;
         max:int64;
    begin
      assign(input,'tictac.in');
      assign(output,'tictac.out');
      reset(input);
      rewrite(output);
      read(n);
      max:=n*n*3+4+6*n;
      write(max);
      close(input);
      close(output);
    end.
    

    第二题

    题目描述

    在n个人中,某些人的银行账号之间可以互相转账。这些人之间转账的手续费各不相同。给定这些人之间转账时需要从转账金额里扣除百分之几的手续费,请问A最少需要多少钱使得转账后B收到100元。

    输入

    第一行输入两个用空格隔开的正整数n和m,分别表示总人数和可以互相转账的人的对数。以下m行每行输入三个用空格隔开的正整数x; y; z,表示标号为x的人和标号为y的人之间互相转账需要扣除z%的手续费(z < 100)。最后一行输入两个用空格隔开的正整数A和B。数据保证A与B之间可以直接或间接地转账。

    输出

    输出A使得B到账100元最少需要的总费用。精确到小数点后8位。

    样例输入

    3 3
    1 2 1
    2 3 2
    1 3 3
    1 3

    样例输出

    103.07153164

    数据范围限制

    对于所有数据, 1 <= n <=2000。


    某个人X 直接给另一个人Y 转账后,假如Y 收到了亡元钱,手续费为:% ,那么X 花费了亡/( 1 一:% )元钱。假如X 和Y 之间可以直接转账且手续费为:%的话,我们连接一条边并赋权值为l / ( 1 一:% )。为了计算A 最少需要花费多少钱,我们需要找到一条路,使得B 到A 走过的路的权值乘积最小。由于权值都是大于1 的数(总是越乘越大),因此我们可以用Dijks 七ra 算法。至于权值乘积最小为什么也能用最短路算法,这可以用Dijkstra 算法的原理来解释,这里不再叙述。


    代码如下:

    var
      max:real;
      n,m,i,j,x,y,z:longint;
      d:array[0..2001]of real;
      v:array[0..2001]of boolean;
      a:array[0..2001,0..2001]of real;
    begin
      assign(input,'money.in');
      reset(input);
      assign(output,'money.out');
      rewrite(output);
      readln(n,m);
      for i:=1 to m do
        begin
          read(x,y,z);
           a[x,y]:=(100-z)/100;
           a[y,x]:=a[x,y];
        end;
      readln(x,y);
      for i:=1 to n do d[i]:=a[x,i];
      d[x]:=1;
      v[x]:=true;
      for i:=1 to n-1 do
        begin
          max:=0;
          for j:=1 to n do
            if not v[j]and(d[j]>max) then
              begin
                max:=d[j];
                z:=j;
              end;
          v[z]:=true;
          for j:=1 to n do
            if not v[j]and(d[z]*a[z,j]>d[j]) then
              d[j]:=d[z]*a[z,j];
        end;
      writeln(100/d[y]:0:8);
      close(input);
      close(output);
    end.

    第三题

    题目描述

    选取和不超过S的若干个不同的正整数,使得所有数的约数(不含它本身)之和最大。

    输入

    输入一个正整数S。

    输出

    输出最大的约数之和。

    样例输入

    11

    样例输出

    9

    数据范围限制

    对于30%的数据, S<=10;
    对于100%的数据, S <=1000。

    提示

    样例说明:
    取数字4和6,可以得到最大值(1 + 2) + (1 + 2 + 3) = 9。


    01背包过


    代码如下:

    var   s,i,ans,j:longint;
          a,b,f:array[0..1000]of longint;
    
    function max(a,b:longint):longint;
    begin
      if a>b then exit(a) else exit(b);
    end;
    
    procedure find(x:longint);
    var  i,l:longint;
    begin
      l:=0;
      for i:=1 to x-1 do
        if x mod i=0 then inc(b[x],i);
    end;
    
    begin
      assign(input,'maxsum.in');
      assign(output,'maxsum.out');
      reset(input);
      rewrite(output);  
      read(s);
      ans:=0;
      for i:=1 to s do
        begin
          find(i);
          a[i]:=i;
        end;
      for i:=1 to s do
        for j:=s downto a[i] do
          f[j]:=max(f[j-a[i]]+b[i],f[j]);
      write(f[s]);
      close(input);
      close(output);
    end.

    第四题

    题目描述

    也许你用过Microsoft Excel之类的电子制表软件,这类软件最令人称道的就是强大的公式计算功能。现在希望你也来实现一个具有最基本功能的电子制表软件。表格共有m列(0 < m • 26),从左到右依次用A到Z的大写英文字母表示;有n行(0 < n <100),从上到下依次用1到100的整数表示。这样,每一个单元格的位置就可以唯一地用它所在的列和行表示出来,例如从左到右第3列,从上到下第5行的单元格就可以用“ C5”来表示(注意,这里字母和数字中间没有空格)。
    现在对表格进行了一系列的操作,这些操作主要就是赋值和查询。定义操作的输入规则
    如下:
    1.每个操作占一行,根据操作类型的不同,每行中可能有二至四个用空格隔开的“单词”;
    2.每行的第一个单词指定了该操作涉及的单元格的位置;
    3.每行的第二个单词指定了相应的操作,可能是: input,output,sum,avg
    (1).如果第二个单词是input,表示接下来的一个整数是要赋予该单元格的值,这个值是
    不超过1000的正整数
    (2).如果第二个单词是output,表示你需要在输出文件中输出这个单元格当前的值
    (3).如果第二个单词是sum,表示接下来输入的两个单词定义了一个矩形区域,该单元格的值就应该恒为这个矩形区域中所包含的单元格的值的和,直到该单元格被重新定义
    (4).如果第二个单词是avg,表示接下来输入的两个单词定义了一个矩形区域,该单元格的值就应该恒为这个矩形区域中所包含的单元格的值的算术平均数,直到该单元格被重新定义;
    4.“输入的两个单词定义了一个矩形区域”是指输入一个矩形区域的左上角和右下角的单元格的位置,这样就唯一确定了这个矩形区域;
    5.所有时刻,每个单元格的值均为整数,如果不是,则向下取整;
    6.如果某个单元格的值没有在上文定义,则它的值默认为0;
    7.不会出现循环定义的情况;
    8.在操作过程中所有单元格的值不超过231-1。

    输入

    第一行输入两个用空格隔开的正整数m和n,分别代表表格的列数和行数。
    第二行输入一个正整数s,表示操作的总数。
    以下s行每行输入一个操作,具体格式参见问题描述。

    输出

    对于输入数据的每一个“ output”操作输出一行结果。因此,输出文件的行数等于输入文
    件中“ output”操作的个数。

    样例输入

    3 5
    5
    A1 input 100
    B2 input 200
    C3 sum A1 C2
    C5 avg B2 C4
    C5 output

    样例输出

    83

    数据范围限制

    对于30%的数据, m; n; s <= 10;
    对于100%的数据, m <= 26, n < =100, s <=100。


    现将input的值全部存起来,如果出现output或sum或avg先存起来
    后面寻找output的值时,再一个一个往回去带。
    

    代码如下:

    var  a:array ['A'..'Z',1..100,1..4] of longint;
         b:array ['A'..'Z',1..100,1..2] of char;
         c,k,x:char;
         i,m,s,y,t:longint;
    
    function as(x:char;y:longint):longint;
    var
      i:char;
      j:longint;
      s:real;
    begin
      case a[x,y,1] of
        0:exit(0);
        1:exit(a[x,y,2]);
        else
          begin
            s:=0;
            for i:=b[x,y,1] to b[x,y,2] do
              for j:=a[x,y,2] to a[x,y,3] do s:=s+as(i,j);
            if a[x,y,1]=3 then exit(trunc(s/a[x,y,4])) else exit(trunc(s));
          end;
      end;
    end;
    
    begin
      assign(input,'excel.in');
      assign(output,'excel.out');
      reset(input);
      rewrite(output);
      read(m);
      readln(m);
      readln(s);
      for t:=1 to s do
        begin
          read(x,y);
          read(k);
          read(c);
          case c of
            'i':begin
                  for i:=1 to 5 do read(k);
                  readln(a[x,y,2]);
                  a[x,y,1]:=1;
                end;
            'o':begin
                  readln;
                  writeln(as(x,y));
                end;
            else
              begin
                for i:=1 to 3 do read(k);
                readln(b[x,y,1],a[x,y,2],k,b[x,y,2],a[x,y,3]);
                if c='s' then a[x,y,1]:=2
                else
                  begin
                    a[x,y,1]:=3;
                    a[x,y,4]:=(ord(b[x,y,2])-ord(b[x,y,1])+1)*(a[x,y,3]-a[x,y,2]+1);
                  end;
              end;
          end;
        end;
      close(input);
      close(output);
    end.
    
  • 相关阅读:
    echo和tee的使用
    cut列的截取
    BZOJ1414: [ZJOI2009]对称的正方形(二维hash)
    BZOJ1010: [HNOI2008]玩具装箱toy
    BZOJ2588: Spoj 10628. Count on a tree(主席树)
    BZOJ3991: [SDOI2015]寻宝游戏(set+lca / 虚树)
    BZOJ2286: [Sdoi2011]消耗战(虚树)
    Linux
    奇妙的棋盘(建图+搜索)
    礼物(动态规划)
  • 原文地址:https://www.cnblogs.com/Comfortable/p/8412448.html
Copyright © 2011-2022 走看看