zoukankan      html  css  js  c++  java
  • CERC 2013 Magical GCD

    题目大意如下:给定一个序列,每个序列有值xi,现给定t个数列,对于每个长n的数列,求一段[l,r]使 [r-l+1]*gcd(l,r)最大,gcd(l,r)指的是该连续区间的最大公约数。

    不难想到n^3,n^2logx,n^2的暴力吧

    n^3DP,n^2logx暴力枚举,n^2DP

    可以这样考虑,每次我对于某一个数,保存若干个值,以i为右端点的区间且gcd为某一值的时候这个区间最大的左端点位置是哪里?

    但是你也许会认为这样做状态会不会有点多?更新是不是n方的呢?

    其实不是的,因为我们可以从左到右来递推。

    什么意思呢?对于每一个数,它与前面构成的gcd一定不会太多(约数肯定不会太多),所以我们最多也只需要保存每一个约数为gcd的时候左边最远能够拓展的位置。

    其实远远不要保存每一个约数的位置,因为实际上很多的约数都不是gcd,这样我们就可以由左边的所有状态和右边的一个gcd一次来递推了。

    当然,我们也可以直接利用指针的自动排序特性(类似链式前向星),我们碰到一个比当前(r-l+1)*val要小的就更新,因为我们再也尝试不到比它大的了。

    {$inline on}
    
    const maxn=100100;
    
    type edge=^node;
        node=record
        next,last:edge;
        pos,val:int64;
    end;
    
    var head,tail:edge;
        e:array [0..maxn] of edge;
        n,cnt:longint;
        ans:int64;
        f:array [0..maxn] of int64;
    
    procedure addedge(pos,value:int64); inline; 
    var p:edge;
    begin
        inc(cnt);
        new(p);
        p^.next:=head^.next;
        p^.last:=head;
        p^.next^.last:=p;
        p^.last^.next:=p;
        p^.pos:=pos; 
        p^.val:=value;
        e[cnt]:=p;
    end;
    
    procedure delete(var p:edge); inline;
    begin
        p^.last^.next:=p^.next;
        p^.next^.last:=p^.last;
    end;
    
    procedure init; inline;
    begin
        ans:=0;
        cnt:=0;
        head^.val:=0; tail^.val:=0;
        head^.next:=tail; tail^.last:=head;
        head^.last:=nil; tail^.next:=nil;
    end;
    
    function gcd(a,b:int64):int64; inline;
    begin
        if a mod b=0 then exit(b)
        else exit(gcd(b,a mod b));
    end;
    
    function max(x,y:int64):int64; inline;
    begin
       if x>y then exit(x)
       else exit(y);
    end;
    
    procedure main;
    var t,value:int64;  i:longint; p:edge;
    begin
        read(t);
        new(head); new(tail);
        while t<>0 do
            begin
                dec(t);
                init;
                read(n);
                ans:=0;
                    for i:=1 to n do
                        begin
                            read(value);
                            addedge(i,value);
                            p:=head^.next;
                                while p<>tail do
                                    begin
                                        p^.val:=gcd(p^.val,value);    
                                        ans:=max(ans,p^.val*(i-p^.pos+1));
                                        if p^.val=p^.last^.val then delete(p^.last);
                                        p:=p^.next;
                                    end;
                        end;
                writeln(ans);
            end;
    end;
    
    begin
          main;
    end.
  • 相关阅读:
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    jQuery火箭图标返回顶部代码
    Codeforces Round #571 (Div. 2)-D. Vus the Cossack and Numbers
  • 原文地址:https://www.cnblogs.com/logichandsome/p/4057122.html
Copyright © 2011-2022 走看看