zoukankan      html  css  js  c++  java
  • jzoj4213. 对你的爱深不见底

    Description

    出乎意料的是,幸运E 的小R 居然赢了那个游戏。现在欣喜万分的小R 想要写一张明信片给小Y,但是因为小R 非常羞涩,所以他打算采用一些比较神奇的方式来表达。
    他定义了一些字符串,s1 = a,s2 = b,si =s_i-1 + s_i-2 (i >=3)。同时他定义了一个字符串s 的权值为一个最大的i <|s|满足s 长度为i 的前缀等于长度为i 的后缀。比如字符串aba 的权值就是1,abab 的权值就是2,aaaa 的权值就是3。
    现在小R 在明信片上给出了两个数n 和m,他想要告诉小Y 的信息是字符串sn 的前m个字符组成的字符串的权值。你可以帮小Y 计算一下吗?

    Input

    第一行输入一个正整数T 表示数据组数。
    对于每组数据,第一行是两个整数n;m。保证1<= m <=|sn|

    Output

    对于每组数据,输出一个整数表示答案。答案可能很大,你只需要输出模258280327 后的答案。

    Sample Input

    2
    4 3
    5 5

    Sample Output

    1
    2

    Data Constraint

    对于30% 的数据,n <= 20
    对于60% 的数据,n <= 60
    对于100% 的数据,n <= 10^3,1 <= T <= 100

    题解

    首先,我们直接上结论——
    当最小的n满足Sn&gt;m+1|S_n|&gt;m+1时,答案即为mSn2m-|S_{n-2}|
    证明?
    我们发现——
    Sn=Sn1+Sn2S_n=S_{n-1}+S_{n-2}
    那么Sn=Sn2+Sn3+Sn2S_n=S_{n-2}+S_{n-3}+S_{n-2}
    Sn=Sn3+Sn4+Sn3+Sn3+Sn4S_n=S_{n-3}+S_{n-4}+S_{n-3}+S_{n-3}+S_{n-4}
    Sn=Sn3+Sn4+Sn3+Sn4+Sn5+Sn4S_n=S_{n-3}+S_{n-4}+S_{n-3}+S_{n-4}+S_{n-5}+S_{n-4}
    Sn=Sn2+Sn2+Sn5+Sn4S_n=S_{n-2}+S_{n-2}+S_{n-5}+S_{n-4}
    接下来我们考虑第二个Sn2S_{n-2}向右延展的可行性。
    也就是当m=Sn22m=|S_{n-2}*2|时,向右可否得到后缀与前缀的大小+1.
    那么SnS_n可表示为:
    Sn5+Sn6+Sn5+Sn4(Sn2)+S_{n-5}+S_{n-6}+S_{n-5}+S_{n-4}(这里前面是S_{n-2}拆出来的式子)+
    Sn5+Sn6+Sn5+Sn4+S_{n-5}+S_{n-6}+S_{n-5}+S_{n-4}+
    Sn5+Sn4S_{n-5}+S_{n-4}
    我们发现,从第一行开始数5项与从第二行开始数5项是可以匹配的。
    紧接着我们发现,当前只有这个Sn4S_{n-4}不匹配。
    怎么办?
    告诉你,可以把这个继续和上面的Sn6S_{n-6}两个拆,但是无法拆尽。
    然而到最后会变成只有最后两个字符不匹配。
    所以就会不满足m+1这个条件。
    然而把原来的那个n+1变成满足m+1这个条件之后,
    又可以继续匹配了。
    感性+画图理解理解就可以了。
    (其实可以用数学归纳法)

    至此,证毕。

    最后,只要打个高精度即可。
    (我把加减乘除都打上去了,目的就是为了那个逗比的mod)

    代码

    type
            new=array[0..1200] of int64;
    var
            i,j,k,l,m,t,ii:longint;
            p,q,op,ok:int64;
            s,nn:ansistring;
            kg:char;
            answer,n,x1,c1,c2,l1,l2,now,pp,ans1,ans2:new;
    
    
    function jian(a,b:new):new;
    var
            ii,jj:longint;
            c:new;
    begin
            fillchar(c,sizeof(c),0);
            if a[0]<b[0] then c[0]:=b[0]
            else c[0]:=a[0];
            for ii:=1 to c[0] do
            begin
                    c[ii]:=c[ii]+a[ii]-b[ii];
                    if c[ii]<0 then
                    begin
                            inc(c[ii],1000000000);
                            dec(c[ii+1]);
                    end;
            end;
            while (c[0]>1)and(c[c[0]]=0) do dec(c[0]);
            exit(c);
    end;
    function plus(a,b:new):new;//inline;
    var
            ii,jj:longint;
            c:new;
    begin
            fillchar(c,sizeof(c),0);
            if a[0]<b[0] then c[0]:=b[0]
            else c[0]:=a[0];
            for ii:=1 to c[0] do
            begin
                    if c[ii]+a[ii]+b[ii]>1000000000 then
                    begin
                            c[ii+1]:=1;
                            c[ii]:=(c[ii]+a[ii]+b[ii])mod 1000000000;
                    end
                    else
                    c[ii]:=c[ii]+a[ii]+b[ii];
            end;
            while c[c[0]+1]=1 do
            begin
                    inc(c[0]);
            end;
            exit(c);
    end;
    procedure insert(st:ansistring; var x:new);inline;
    var
            len:longint;
    begin
            len:=length(st);
            while len>=9 do
            begin
                    inc(x[0]);
                    val(copy(st,len-8,9),x[x[0]]);
                    dec(len,9);
            end;
    
            if len>0 then
            begin
                    inc(x[0]);
                    val(copy(st,1,len),x[x[0]]);
            end;
    end;
    procedure print(a:new);inline;
    var
            ii:longint;
    begin
            write(a[a[0]]);
            for ii:=a[0]-1 downto 1 do
            begin
                    if a[ii]<100000000 then write(0);
                    if a[ii]<10000000 then write(0);
                    if a[ii]<1000000 then write(0);
                    if a[ii]<100000 then write(0);
                    if a[ii]<10000 then write(0);
                    if a[ii]<1000 then write(0);
                    if a[ii]<100 then write(0);
                    if a[ii]<10 then write(0);
                    write(a[ii]);
            end;
    end;
    function max(a,b:new):boolean;
    var
            i,j,k:longint;
    begin
            if a[0]<b[0] then exit(false);
            if a[0]>b[0] then exit(true);
            for i:=a[0] downto 1 do
            begin
                    if a[i]>b[i] then exit(true);
                    if a[i]<b[i] then exit(false);
            end;
            exit(false);
    end;
    function divv(a:new; b:int64):new;
    var
            ii:longint;
            xx:int64;
            c:new;
    begin
            xx:=0;
            fillchar(c,sizeof(c),0);
            c[0]:=a[0];
            for ii:=a[0] downto 1 do
            begin
                    c[ii]:=xx*1000000000+a[ii];
                    xx:=c[ii] mod b;
                    c[ii]:=c[ii] div b;
            end;
            while (c[0]>1)and(c[c[0]]=0)do dec(c[0]);
            exit(c);
    end;
    function cheng(a,b:new):new;
    var
            ii,jj:longint;
            c:new;
    begin
            fillchar(c,sizeof(c),0);
            c[0]:=a[0]+b[0]-1;
            for ii:=1 to a[0] do
            for jj:=1 to b[0] do
            begin
                    c[ii+jj]:=c[ii+jj]+(c[ii+jj-1]+a[ii]*b[jj])div 1000000000;
                    c[ii+jj-1]:=(c[ii+jj-1]+a[ii]*b[jj])mod 1000000000;
            end;
            while c[c[0]+1]>0 do inc(c[0]);
            exit(c);
    end;
    begin
            readln(t);
            while t>0 do
            begin
                    dec(t);
                    fillchar(n,sizeof(n),0);
                    fillchar(now,sizeof(now),0);
                    read(m,kg);
                    readln(nn);
                    insert(nn,n);
                    c1[0]:=1;c1[1]:=1;
                    c2[0]:=1;c2[1]:=258280327;
                    n:=plus(n,c1);
                    l1:=c1;l2:=c1;now:=plus(l1,l2);
                    while not max(now,n) do
                    begin
                            pp:=now;
                            now:=plus(now,l2);
                            l1:=l2;
                            l2:=pp;
                            if now[0]=2 then
                            begin
                                    j:=j;
                            end;
                    end;
                    n:=jian(n,c1);
                    ans1:=jian(n,l1);
                    ans2:=divv(ans1,258280327);
                    answer:=cheng(ans2,c2);
                    answer:=jian(ans1,answer);
                    print(answer);
                    writeln;
            end;
    end.
    
  • 相关阅读:
    DEDECMS里面DEDE函数解析
    dede数据库类使用方法 $dsql
    DEDE数据库语句 DEDESQL命令批量替换 SQL执行语句
    织梦DedeCms网站更换域名后文章图片路径批量修改
    DSP using MATLAB 示例 Example3.12
    DSP using MATLAB 示例 Example3.11
    DSP using MATLAB 示例 Example3.10
    DSP using MATLAB 示例Example3.9
    DSP using MATLAB 示例Example3.8
    DSP using MATLAB 示例Example3.7
  • 原文地址:https://www.cnblogs.com/RainbowCrown/p/11148366.html
Copyright © 2011-2022 走看看