• 解题报告 数字查找


    1.        题目

    1. 数字查找

        find.pas/c/cpp

    【题目描述】

    XY在玩一个非常有意思的游戏,X在纸上写了n个数字,然后XY提一些问题,Y来回答。

    “你知道这些数字中两两结合组成的和不超过M1的有多少种吗?”

    “这太简单了!有K1种!”

    “你知道这些数字中两两结合组成的和不超过M2的有多少种吗?”

    “这太简单了!有K2种!”

    “你知道这些数字中两两结合组成的和不超过M3的有多少种吗?”

    “这太简单了!有K3种!”

    “你知道……”

    “烦不烦!不知道!”

    就这样,Y怒了。

    但是Y仔细一想,不能和X一般见识,但是又不愿意回答如此单调的问题。所以Y请你来帮忙。

     

    【输入格式】

    第一行一个数n,表示数字的个数;

    第二行到第n+1行,每行一个不超过2,000,000,000的数k

    n+2行一个数m,表示m个问题;

    n+3行到第n+m+2行,每行一个数M,询问表示n中两两组合不超过M的组合的个数;

     

    【输出格式】

    输出m行,每行对应一个答案

     

    【输入样例】

    3

    1

    2

    3

    2

    2

    3

     

    【输出样例】

    0

    1

     

    【数据范围】

    30%的数据1<=n<=1001<=m<=50k<=2000;

    100%的数据 1<=n<=10000, 1<=m<=100,k<=2,000,000,000;

     

    2.        算法

    过掉他,有两种途径:

    二分,不解释。

    先排序,然后左端点枚举,右端点一直向右走.......

     

    越说越乱,继续上代码。

    (怎么我的语文越来越不好了?)

    3.        注意事项

    枚举是要优化的。

    觉得第二种不保险就打二分吧。

    4.        代码

    二分 (Leve)

    var

     n,i,j,l,r,mid,op,mm,ii,ans:longint;

     m:int64;

     a:array[1..10000] of int64;

    procedure qs(r,l:longint);

     var

      i,j:longint;

      x,y:int64;

     begin

      i:=r; j:=l;

      x:=a[(i+j)>>1];

      repeat

       while a[i]<x do inc(i);

       while a[j]>x do dec(j);

        if i<=j then

     begin

      y:=a[i];

      a[i]:=a[j];

      a[j]:=y;

      inc(i);

      dec(j);

     end;

      until i>j;

     if i<l then qs(i,l);

     if j>r then qs(r,j);

    end;

    begin

     assign(input,'find.in');

     assign(output,'find.out');

     reset(input);

     rewrite(output);

     readln(n);

     for i:=1 to n do

      readln(a[i]);

     qs(1,n);

     readln(mm);

     for ii:=1 to mm do

      begin

       readln(m);

       ans:=0;

       for i:=1 to n do

        begin

     l:=i+1; r:=n;

             op:=0;

     while l<=r do

      begin

       mid:=(l+r)>>1;

       if a[i]+a[mid]<=m then

        begin

     op:=mid;

     l:=mid+1;

    end

    else

    r:=mid-1;

       end;

             if op>i then

     ans:=ans+op-i;

       end;

      writeln(ans);

      end;

      close(input);

      close(output);

    end.

     

     

     

    枚举优化 (SueMiller)

    var n:longint;

        a:array[0..10001]of int64;

        i,j,k:longint;

        m,l,r,mid,ans:longint;

        mm:double;

        x:int64;

     

    procedure quicksort(l,r:longint);

    var i,j:longint;x,y:int64;

    begin

     i:=l; j:=r; x:=a[(l+r)>>1];

     repeat

      while a[i]<x do inc(i);

      while x<a[j] do dec(j);

      if i<=j then

       begin

       y:=a[i]; a[i]:=a[j]; a[j]:=y;

       inc(i); dec(j);

       end;

     until i>j;

     if l<j then quicksort(l,j);

     if i<r then quicksort(i,r);

    end;

     

    begin

      assign(input,'find.in');reset(input);

      assign(output,'find.out');rewrite(output);

     

      fillchar(a,sizeof(a),0);

      readln(n);

      for k:=1 to n do

        readln(a[k]);

     

      quicksort(1,n);

     

      readln(m);

      for k:=1 to m do

        begin

          readln(x);

          r:=n;

          ans:=0;

          for l:=1 to n do

            begin

              while a[l]+a[r]>x do dec(r);

              if r<l then break;

              ans:=ans+r-l;

            end;

          writeln(ans);

        end;

      close(input);close(output);

    end.

     

  • 相关阅读:
    【京东面试复盘】一面二面真题面经解析
    4个小技巧带你轻松入门kafka!
    python 函数
    python 文件修改
    python 文件基本操作
    python 集合的一些用法
    python 字典的应用_简单的三级列表
    python 字典的一些用法
    python 字符串的一些用法
    python 列表应用-简单的购物车
  • 原文地址:https://www.cnblogs.com/SueMiller/p/2213452.html
Copyright © 2020-2023  润新知