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满足 ∣ S n ∣ &gt; m + 1 |S_n|&gt;m+1 Sn>m+1时,答案即为 m − ∣ S n − 2 ∣ m-|S_{n-2}| mSn2
证明?
我们发现——
S n = S n − 1 + S n − 2 S_n=S_{n-1}+S_{n-2} Sn=Sn1+Sn2
那么 S n = S n − 2 + S n − 3 + S n − 2 S_n=S_{n-2}+S_{n-3}+S_{n-2} Sn=Sn2+Sn3+Sn2
S n = S n − 3 + S n − 4 + S n − 3 + S n − 3 + S n − 4 S_n=S_{n-3}+S_{n-4}+S_{n-3}+S_{n-3}+S_{n-4} Sn=Sn3+Sn4+Sn3+Sn3+Sn4
S n = S n − 3 + S n − 4 + S n − 3 + S n − 4 + S n − 5 + S n − 4 S_n=S_{n-3}+S_{n-4}+S_{n-3}+S_{n-4}+S_{n-5}+S_{n-4} Sn=Sn3+Sn4+Sn3+Sn4+Sn5+Sn4
S n = S n − 2 + S n − 2 + S n − 5 + S n − 4 S_n=S_{n-2}+S_{n-2}+S_{n-5}+S_{n-4} Sn=Sn2+Sn2+Sn5+Sn4
接下来我们考虑第二个 S n − 2 S_{n-2} Sn2向右延展的可行性。
也就是当 m = ∣ S n − 2 ∗ 2 ∣ m=|S_{n-2}*2| m=Sn22时,向右可否得到后缀与前缀的大小+1.
那么 S n S_n Sn可表示为:
S n − 5 + S n − 6 + S n − 5 + S n − 4 ( 这 里 前 面 是 S n − 2 拆 出 来 的 式 子 ) + S_{n-5}+S_{n-6}+S_{n-5}+S_{n-4}(这里前面是S_{n-2}拆出来的式子)+ Sn5+Sn6+Sn5+Sn4(Sn2)+
S n − 5 + S n − 6 + S n − 5 + S n − 4 + S_{n-5}+S_{n-6}+S_{n-5}+S_{n-4}+ Sn5+Sn6+Sn5+Sn4+
S n − 5 + S n − 4 S_{n-5}+S_{n-4} Sn5+Sn4
我们发现,从第一行开始数5项与从第二行开始数5项是可以匹配的。
紧接着我们发现,当前只有这个 S n − 4 S_{n-4} Sn4不匹配。
怎么办?
告诉你,可以把这个继续和上面的 S n − 6 S_{n-6} Sn6两个拆,但是无法拆尽。
然而到最后会变成只有最后两个字符不匹配。
所以就会不满足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.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值