[SGU]111. Very simple problem

Analysis

    不要被标题迷惑了!没那么看上去简单哟!刚看这题总觉得似曾相识,复习初赛的时候才发现是去年初赛完善程序的第一题……不过把那个程序交上去应当是会TLE的吧……因为它没压位……我的AC程序是二分+压位高精。据说还有笔算开方的算法,我果然小学数学没学好T T……

Accepted Code

var
    a,l,r,mid,sqrmid,tmp:array[0..1100] of int64;
    lens,lenl,lenr,lenmid,lensqrmid,i,j:longint;
    s:ansistring;
    bo1,bo2:boolean;

function comp:boolean;
var
    bo:boolean;
    i:longint;
begin
    if not bo2 then
    begin
        tmp:=l;
        inc(tmp[1]);
        i:=1;
        while tmp[i]>99999999 do
        begin
            inc(tmp[i+1]);
            dec(tmp[i],100000000);
            inc(i);
        end;
        bo2:=true;
    end;
    bo:=true;
    for i:=1 to lenr do
    begin
        bo:=bo and (r[i]=tmp[i]);
        if not bo then
            break;
    end;
    comp:=bo;
end;

procedure calcsqrmid;
var
    i,j:longint;
begin
    fillchar(sqrmid,sizeof(sqrmid),0);
    for i:=1 to lenmid do
        for j:=1 to lenmid do
            sqrmid[i+j-1]:=sqrmid[i+j-1]+mid[i]*mid[j];
    lensqrmid:=lenmid shl 1;
    for i:=1 to lensqrmid do
    begin
        sqrmid[i+1]:=sqrmid[i+1]+sqrmid[i] div 100000000;
        sqrmid[i]:=sqrmid[i] mod 100000000;
    end;
    if sqrmid[lensqrmid]=0 then
        dec(lensqrmid);
end;

begin
    readln(s);
    lens:=length(s) div 8;
    if length(s) mod 8<>0 then
        inc(lens);
    i:=1;
    while lens>i do
    begin
        val(copy(s,length(s)-7,length(s)),a[i],lenl);
        delete(s,length(s)-7,8);
        inc(i);
    end;
    val(s,a[i],lenl);
    fillchar(l,sizeof(l),0);
    l[1]:=1;
    lenl:=1;
    fillchar(r,sizeof(r),0);
    r[131]:=1;
    lenr:=131;
    bo2:=false;
    repeat

        fillchar(mid,sizeof(mid),0);
        for i:=1 to lenr do
        begin
            mid[i]:=mid[i]+l[i]+r[i];
            if mid[i]>=100000000 then
            begin
                mid[i]:=mid[i]-100000000;
                mid[i+1]:=1;
            end;
        end;
        if mid[lenr+1]>0 then
            lenmid:=lenr+1
        else
            lenmid:=lenr;
        for i:=lenmid downto 1 do
        begin
            if mid[i] and 1>0 then
                inc(mid[i-1],100000000);
            mid[i]:=mid[i] shr 1;
        end;
        if mid[lenmid]=0 then
            dec(lenmid);

        if (lenmid*2<lens) or (lenmid*2-1>lens) then
            bo1:=lenmid*2-1>lens
        else
        begin
            calcsqrmid;
            if lensqrmid<>lens then
                bo1:=lensqrmid>lens
            else
            begin
                i:=lens;
                while (i>0) and (sqrmid[i]=a[i]) do
                    dec(i);
                bo1:=sqrmid[i]>a[i];
            end;
        end;
        if bo1 then
        begin
            r:=mid;
            lenr:=lenmid;
        end
        else
        begin
            l:=mid;
            lenl:=lenmid;
            bo2:=false;
        end;
        if lenl+1<lenr then
            continue;
    until comp();
    write(l[lenl]);
    for i:=lenl-1 downto 1 do
    begin
        str(l[i],s);
        while length(s)<8 do
            s:='0'+s;
        write(s);
    end;
    writeln;
end.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值