• 2017.7.8 C组总结


    NO.1

    题目描述:
    小x和小y是好朋友。小y的成绩很差,以至于 GPA(平均绩点)在系内倒数。系内一共有 N 位同学,每位同学有自己的 GPA,以及已修学分数,定义 GPT = GPA ×已修学分数。小x为了帮助小y提高成绩,给小y提了一个要求:新学期的 GPA 要超过系内排名第 K 位的同学。 为了帮助理解,给出一个例子:
    现在给出系里面每位同学的 GPT(只有一位小数),以及他们的已修学分。你需要帮助小y把排名 第 K 位的同学的 GPA 求出来。
    这里写图片描述

    思路:排序
    就是求出GPA的第k位,那么一个快速排序就可yi1求出

    代码:

    var i,n,k,y:longint;
        x:real;
        a:array[0..100001]of real;
    
    procedure qsort(l,r:longint);
    var  i,j:longint; mid:real;
    begin
      if l>=r then exit;
      i:=l; j:=r; mid:=a[(l+r) 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,'sort.in');
      assign(output,'sort.out');
      reset(input);
      rewrite(output);
      readln(n,k);
      for i:=1 to n do
        begin
          readln(x,y);
          a[i]:=x/y;
        end;
      qsort(1,n);
      writeln(a[k]:0:2);
      close(input);
      close(output);
    end.

    NO.2

    题目描述:
    小x有很多糖果,分成了 N 堆,排成一列。小x说,如果小y能迅速求出第 L 堆到第 R 堆一 共有多少糖果,就把这些糖果都给他。
    现在给出每堆糖果的数量,以及每次询问的 L 和 R,你需要帮助小y,把每次询问的结果求出来。 注意,你不需要考虑糖果被小y取走的情况。

    思路:前缀和
    设sum[i]为前i堆糖果的和
    求区间[x…y]就是sum[y]-sum[x-1]

    代码:

    var   x,y,n,m,i:longint;
          a,sum:array[0..100001]of int64;
    begin
      assign(input,'sum.in');
      assign(output,'sum.out');
      reset(input);
      rewrite(output);
      readln(n,m);
      for i:=1 to n do begin read(a[i]); sum[i]:=sum[i-1]+a[i]; end;
      readln;
      for i:=1 to m do
        begin
          readln(x,y);
          writeln(sum[y]-sum[x-1]);
        end;
      close(input);
      close(output);
    end.
    

    NO.3

    题目描述:
    小x开发了一个奇怪的游戏,这个游戏的是这样的:一个长方形,被分成 N 行 M 列的格子,第 i 行第 j 列的格子记为 (i, j),就是说,左上角的格子是 (1, 1),右下角的格子是 (N, M)。开始的时候,小y在 (1, 1),他需要走到 (N, M)。每一步,小y可以走到正右方或者正下方的一个格子。具体地说,如小y现在在 (x, y),那么他可以走到 (x, y + 1) 或 (x + 1, y)。当然,小y不能走出离开这个长方形。
    每个格子有积分,用一个 1~10 的整数表示。经过这个格子,就会获取这个格子的积分(起点和终 点的积分也计算)。通过的方法是:到达 (N, M) 的时候,积分恰好为 P 。
    现在给出这个长方形每个格子的积分,你需要帮助小y,求出从起点走到终点,积分为 P 的线路有多少条。

    思路:递推
    设f[i,j,k]为走到(i,j),积分为k的路线有多少条
    递推式为f[i,j,k]=f[i,j,k]+f[i-1,j,k-a[i,j]]+f[i,j-1,k-a[i,j]]

    代码:

    const mo=1000000007;
    var n,m,p,i,j,k:longint;
        f:array[0..101,0..101,-10..1501]of longint;
        a:array[0..101,0..101]of longint;
    begin
      assign(input,'count.in');
      assign(output,'count.out');
      reset(input);
      rewrite(output);
      readln(n,m,p);
      for i:=1 to n do
        begin
          for j:=1 to m do read(a[i,j]);
          readln;
        end;
      f[0,1,0]:=1;
      for i:=1 to n do
        for j:=1 to m do
          for k:=a[i,j] to p do
            f[i,j,k]:=(f[i,j,k]+f[i-1,j,k-a[i,j]]+f[i,j-1,k-a[i,j]]) mod mo;
      write(f[n,m,p]);
      close(input);
      close(output);
    end.

    NO.4

    题目描述:
    小x有n个小姊妹(根据典故,我们假设n≤3000)。他每天都喜欢按不同标准给小姊妹们排(da)序(fen)。今天,他突然对小姊妹们的名字产生了兴趣。他觉得小姊妹的魅力和她们的名字有密切联系,于是他觉得所有有相似的名字的小姊妹必须排在一起。
    相似是指,名字的开头一个或若干个连续字母相同。
    于是,小x定下了如下规则:
    在任何以同样的字母序列开头的名字之间,所有名字开头必须是同样的字母序列。
    比如,像MARTHA和MARY这两个名字,它们都以MAR开头,所以像MARCO或MARVIN这样的名字可以插入这两个名字中间,而像MAY这样的就不行。
    显然,按字典序排序是一个合法的排序方案,但它不是唯一的方案。你的任务就是计算出所有合法的方案数。考虑到答案可能很大,输出答案 mod 1 000 000 007。

    思路:DFS+数学+排序+分治
    首先,要求出每一个名字的长度,并将其补位
    然后从小到大排序名字
    设s[i]为i的阶乘,公式:s[i]:=(s[i-1]*i) mod 1000000007
    求出来这个然后就开始DFS SHOW!!
    从第x个名字的第z个字母开始,向后寻找不等于的名字的位置,然后分段,分治(分开处理)
    那么第x个名字到第y个名字为一组,递归,再分治(dfs(k,i-1,z+1))
    然后将不等于的名字的第z位,向上面那样,找到第一个不等于的位置,再分段
    如果没有找到,就将等于的分为一段,再继续寻找(dfs*dfs(k,y,z+1))
    每次分了多少段就要乘相应段数的阶乘
    (其实这个DFS本质想实现的就是分治)

    代码:

    var a:array[0..3000]of ansistring;
        l:array[0..3000]of longint;
        s:array[0..3000]of int64;
        i,j,max,n,m:longint;
    
    function dfs(x,y,z:longint):int64;
    var  t,i,k:longint;
         s1:char;
    begin
      if z>max then exit(s[y-x+1]);
      k:=x; s1:=a[x,z]; dfs:=1; t:=1;
      for i:=x+1 to y do
        if a[i,z]<>s1 then
          begin
            inc(t);
            dfs:=(dfs*dfs(k,i-1,z+1) mod 1000000007)mod 1000000007;
            k:=i;
            s1:=a[i,z];
          end;
      if k<>y then dfs:=(dfs*dfs(k,y,z+1)) mod 1000000007;
      dfs:=(dfs*s[t]) mod 1000000007;
    end;
    
    procedure qsort(l,r:longint);
    var  i,j:longint;
         mid,t:ansistring;
    begin
      if l>=r then exit;
      i:=l; j:=r; mid:=a[(l+r) div 2];
      repeat
        while a[i]<mid do inc(i);
        while a[j]>mid do dec(j);
        if i<=j then
          begin
            t:=a[i];
            a[i]:=a[j];
            a[j]:=t;
            inc(i);
            dec(j);
          end;
      until i>=j;
      qsort(l,j);
      qsort(i,r);
    end;
    
    procedure init;
    begin
      readln(n);
      for i:=1 to n do
        begin
          readln(a[i]);
          l[i]:=length(a[i]);
          if l[i]>max then max:=l[i];
        end;
      for i:=1 to n do
        if l[i]<max then
          for j:=l[i]+1 to max do
            a[i]:=a[i]+'0';
    end;
    
    procedure qpl;
    begin
      s[0]:=1;
      for i:=1 to 3000 do s[i]:=(s[i-1]*i) mod 1000000007;
    end;
    
    begin
      assign(input,'ranking.in');
      assign(output,'ranking.out');
      reset(input);
      rewrite(output);
      init;
      qpl; 
      qsort(1,n);
      writeln(dfs(1,n,1));
      close(input);
      close(output);
    end.
  • 相关阅读:
    关于 UITableView 中 网络获取图片 cell 自适应高度的问题
    iOS开发~CocoaPods使用详细说明
    block的使用
    约数个数
    学习Hibernate的(笔者一共会写四部分)
    八皇后问题
    JAVA(利用jsp+javabean+servlet)实现简易计算器
    学习C++的道路 博主会持续更新的
    高效求解区间约数
    最大化平均值
  • 原文地址:https://www.cnblogs.com/Comfortable/p/8412272.html
Copyright © 2020-2023  润新知