zoukankan      html  css  js  c++  java
  • 解题报告 数学2

    2、数学,又是数学(mathagain)

    其实吧,大家也发现了,这六道题本来是一科一道的,但是呢,由于某某人比较……,就不顾某某人的反对抛弃了我们可爱的English,又出了一道math……

    题目描述

      Liukeke同学(我们敬爱滴亲爱滴可爱滴班长大人)最近又在忙着开班会(真是个工作狂),于是乎,数学学案就被抛到了九霄云外,直到预备铃打完,他才发现那张美丽的雪白的学案,眼看一场血案即将发生,他请你用最快的速度帮他算完第一题:

    给定一个数串,数串的长度为n,现在将一个子串的每个数字之和定义为该子串的数串和,请你求出数串中有多少个子串的数串和为正数。

    输入格式

    第一行一个数n,表示数串的长度。

    第二行一共n个数,表示数串中的每个数

    输出格式

     就一个数,表示数串中有多少个子串的数串和为正数。

    样例输入

    3

    8 -9 2

    样例输出

    3

    数据范围

    30%   n<=1000。

    100%  n<=100000。

     

    Liukeke 的学科试题之五·数学2。(因为此人实在不知道怎么出英语了,⊙﹏⊙b

     

    预处理出累和,不难发现,只要前一个和小于后一个,这两个的差所表示的那一段数列的和就是正数。

     

    然后,就对累和的那个数列归并求顺序对。好吧,我承认我当时把这个算法给忘了。

     

    代码(Liukeke

    var

     a,b:array[0..100000] of longint;

      i,n,t:longint;ans:int64;

     

    procedure merge(l,r:longint);

    var mid,i,j,k:longint;

    begin

     if l=r then exit;

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

     merge(l,mid);merge(mid+1,r);

     i:=l; j:=mid+1; k:=l;

     while (i<=mid) and(j<=r) do

      begin

       if a[i]>=a[j] then begin inc(ans,i-l);b[k]:=a[j];inc(k);inc(j);end

       else begin b[k]:=a[i]; inc(k);inc(i);end;

      end;

     if i<=mid then for j:=i to mid do

                     begin

      b[k]:=a[j];inc(k);

     end

     else for i:=j to r do

           begin

        b[k]:=a[i];inc(k);

    inc(ans,mid-l+1);

       end;

     for i:=l to r do a[i]:=b[i];

    end;

     

    begin

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

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

     readln(n);

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

     for i:=1 to n do

      begin

       read(t);

       a[i]:=t+a[i-1];

      end;

     merge(0,n);

     writeln(ans);

     close(input);close(output);

    end.

     

     

     

     

     

    补充:归并求逆序对。

    type
    arr=array[0..40000] of longint;
    var
    temp,a,b:arr;
    c:array[0..200,0..200] of longint;
    i,j,k,m,n,ans1,ans2:longint;
    procedure hba(l,mid,r:longint);
    var
    i,j,k,kk:longint;
    begin
    i:=l; j:=mid+1;
    for kk:=l to r do
        begin
          if (i<=mid)and((a[i]<=a[j])or(j>r)) then
            begin
              temp[kk]:=a[i];
              inc(i);
            end
          else
            begin
              temp[kk]:=a[j];
              inc(j);
              if i<mid+1 then inc(ans1,mid-i+1);
            end;
        end;
    for kk:=l to r do
        a[kk]:=temp[kk];
    end;

    procedure mergea(s,t:longint);
    var
    k:longint;
    begin
    if s=t then exit;
    k:=(s+t)>>1;
    if k>s then mergea(s,k);
    if t>k+1 then mergea(k+1,t);
    hba(s,k,t);
    end;

    procedure hbb(l,mid,r:longint);
    var
    i,j,k,kk:longint;
    begin
    i:=l; j:=mid+1;
    for kk:=l to r do
        begin
          if (i<=mid)and((b[i]<=b[j])or(j>r)) then
            begin
              temp[kk]:=b[i];
              inc(i);
            end
          else
            begin
              temp[kk]:=b[j];
              inc(j);
              if i<mid+1 then inc(ans2,mid-i+1);
            end;
        end;
    for kk:=l to r do
        b[kk]:=temp[kk];
    end;

    procedure mergeb(s,t:longint);
    var
    k:longint;
    begin
    if s=t then exit;
    k:=(s+t)>>1;
    if k>s then mergeb(s,k);
    if t>k+1 then mergeb(k+1,t);
    hbb(s,k,t);
    end;

    begin
    assign(input,'game.in'); reset(input);
    assign(output,'game.out'); rewrite(output);
    while not eof do
    begin
    readln(n,m);
    for i:=1 to n do
        begin
          for j:=1 to n do read(c[i,j]);
          readln;
        end;
    if odd(m) then
       begin
        for i:=1 to n do
          for j:=1 to n do
            a[(i-1)*n+j]:=c[i,j];
        for j:=1 to n do
          for i:=1 to n do
            b[(j-1)*n+i]:=c[i,j];
       end
    else
        begin
          for i:=1 to n do
            for j:=1 to n do
               b[(i-1)*n+j]:=c[i,j];
          for j:=1 to n do
            for i:=1 to n do
               a[(j-1)*n+i]:=c[i,j];
        end;
    ans1:=0; ans2:=0;
    mergea(1,n*n);
    mergeb(1,n*n);
    if ans1=ans2 then
        writeln('NYY and XYY will try again')
    else
    if ans1<ans2 then
        writeln('NYY wins the Rocket''s Game')
    else
        writeln('XYY wins the Rocket''s Game');
    writeln;
    end;
    close(input); close(output);
    end.

    注:题目中要求求两遍逆序对,就是用归并排序做。需要注意的点:在处理的数据比较多的时候不要再合并时fillchar temp,在递归的时候判断一下大小(红的地方),不然可能栈溢出。

     

  • 相关阅读:
    SQLite 基本使用
    SQLite 语法
    html5晋级之路-css介绍
    html5晋级之路-web storage
    html5晋级之路-元素语法
    html晋级之路-背景、实体
    ios-晋级之路 CocoaPods的使用
    如何在Mac OS X上安装 Ruby运行环境
    html5晋级之路-学习笔记表单
    html5晋级之路-学习笔记
  • 原文地址:https://www.cnblogs.com/SueMiller/p/2224003.html
Copyright © 2011-2022 走看看