zoukankan      html  css  js  c++  java
  • 4和7

    4和7

    由题目m的数据范围可以知道,(m<=1000000000)单纯的转移是不可以的:f[i]:=max(f[i-1],f[i-7])+a[i];

    1. a[i]的数组开不下;
    2. 循环1到1000000000也不太可行

    解决:离散化

    A[i]数组表示每个点的药品价值;b[i]数组表示每个点的位置,进一步观察n的范围(n<=100000),点的数目可以利用。那么前一个点与后一个点有什么关系?

    当b[i]-b[i-1]>18时,将b[i]的坐标更新为b[i-1]+18,这样每两个点之间最大距离为18,位置范围缩小到了18*100000。

    证明:为什么当两个点之间距离>18时距离可以缩小到18,因为大于等于18的数都可以由4和7拼出来,即两个点之间一定能转移。由裴蜀定理ax+by=m,当m为gcd(a,b)的倍数时方程一定有解,但这个题要求x>=0,y>=0,可得到当m>=18时一定有非负整数解。

    F[i]:=max(f[i-4],f[i-7])+c[i];  c[i]就是按照以上方式处理得到的新数列,当两点之间距离>18时就把距离缩到18,当两个点重合时,c[i]为两个点a[i]的累加值。最需注意的一点是:在<=18的范围内,1,2,3,5,6,9,10,13,15,17的c值应为0,因为无法由它转移,所以c值设为0,防止f的转移。

    代码实现:

    program exam;

    uses math;

    var

      i,j:longint;

      n,m,p,ans:int64;

      f:array[-10..2000000] of int64;

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

      c:array[1..2000000] of int64;

      b:array[1..2000000] of int64;

    procedure qsort(l,r:int64);

    var

      x,i,j,y:int64;

    begin

      i:=l;

      j:=r;

      x:=b[(i+j) div 2];

      repeat

        while b[i]<x do

          inc(i);

        while b[j]>x do

          dec(j);

        if i<=j then

        begin

          y:=b[i];

          b[i]:=b[j];

          b[j]:=y;

          y:=a[i];

          a[i]:=a[j];

          a[j]:=y;

          inc(i);

          dec(j);

        end;

      until i>j;

      if (i<r) then

        qsort(i,r);

      if (l<j) then

        qsort(l,j);

    end;

    procedure chuli;

    var

      i,j:longint;

      t,k:int64;

    begin

      t:=0;

      p:=b[1];               // 记录一个新数组上一个点位置

      c[p]:=a[1];

      for i:=2 to n do

      begin

        if b[i]=b[i-1] then

          c[p]:=c[p]+a[i];

        if b[i]<>b[i-1] then

        begin

          if b[i]-b[i-1]>18 then

          begin

            c[p+18]:=a[i];

                p:=p+18;

          end;

          if b[i]-b[i-1]<=18 then

          begin

            k:=b[i]-b[i-1];

            c[p+k]:=a[i];

            p:=p+k;

          end;

        end;

      end;

    end;

    begin

      assign(input,'hop10.in');

      reset(input);

      readln(n,m);

      for i:=1 to n do

        readln(a[i],b[i]);

      qsort(1,n);

      chuli;

      c[1]:=0;

      c[2]:=0;

      c[3]:=0;

      c[5]:=0;

      c[6]:=0;

      c[9]:=0;

      c[10]:=0;

      c[13]:=0;

      c[17]:=0;

      for i:=1 to p do

        f[i]:=max(f[i-4],f[i-7])+c[i];

      for i:=1 to p do

        if ans<f[i] then

          ans:=f[i];

      writeln(ans);

      close(input);

    end.

  • 相关阅读:
    printf,sprintf,fprintf的区别与联系
    linux repo init 遇到的问题
    POSTMAN使用说明
    HTTP协议-深入了解
    HTTP协议-详解篇
    HTTP协议-基础篇
    多线程学习
    I/O流
    String类学习&泛型
    集合
  • 原文地址:https://www.cnblogs.com/fengxiudong/p/6017312.html
Copyright © 2011-2022 走看看