【五校联考1day2】对你的爱深不见底(斐波那契数列+高精度加、减、模)

题面

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

思路

这一类的字符串的特殊性还是挺明显的,打一个表或者找规律就可以发现.

令Si为斐波那契数列第i项,由于会爆long long,要用高精度加减、取模

令 n 为最小的 n 满足 |Sn| > m+1,那么答案就是 m−|Sn−2|。证明还是挺简单的大家脑补一下就好了。时间复杂度 O(N^2 )。

CODE

借鉴code很可能不被你的OI老师所允许,请慎重选择

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<string>
  5 using namespace std;
  6 int n,t,mod=258280327;
  7 struct node
  8 {
  9     int s[10005],len;
 10     void read()
 11     {
 12         char ch=getchar();
 13         len=0;
 14         while(ch<'0'||ch>'9')ch=getchar();
 15         while(ch>='0'&&ch<='9')
 16         {
 17             s[len++]=ch-48;
 18             ch=getchar();
 19         }
 20         for(int j=0;j<len/2;j++)
 21         {
 22             swap(s[j],s[len-j-1]);
 23         }
 24     }
 25     void wrt()
 26     {
 27         for(int i=len-1;i>=0;i--)
 28         {
 29             printf("%d",s[i]);
 30         }
 31         printf("\n");
 32     }
 33 }a[3005],m,ans,tmp;
 34 node sum(node x,node y)
 35 {
 36     node s;s.len=max(x.len,y.len)+3;
 37     for(int i=0;i<max(x.len,y.len)+5;i++)s.s[i]=0;
 38     int last=0;
 39     for(int i=0;i<max(x.len,y.len);i++)
 40     {
 41         s.s[i]=(x.s[i]+y.s[i]+last)%10;
 42         last=(x.s[i]+y.s[i]+last)/10;
 43     }
 44     if(last)s.s[max(x.len,y.len)]=last;
 45     s.len=max(x.len,y.len)+3;
 46     while(s.s[s.len]==0)s.len--;
 47     s.len++;return s;
 48 }
 49 node del(node x,node y)
 50 {
 51     node s;
 52     for(int i=0;i<max(x.len,y.len)+5;i++)s.s[i]=0;
 53     int last=0;
 54     for(int i=0;i<max(x.len,y.len);i++)
 55     {
 56         if(x.s[i]>=y.s[i]+last)
 57         {
 58             s.s[i]=x.s[i]-y.s[i]-last;
 59             last=0;
 60         }
 61         else
 62         {
 63             s.s[i]=10+x.s[i]-y.s[i]-last;
 64             last=1;
 65         }
 66     }
 67     s.len=max(x.len,y.len)+3;
 68     while(s.s[s.len]==0)s.len--;
 69     s.len++;
 70     return s;
 71 }
 72 int modit(node x)
 73 {
 74     long long a=0,b=mod;
 75     for(int i=x.len;i>=0;i--)
 76     {
 77         a=a*10+x.s[i];
 78         if(a>=b)
 79         {
 80             a=a%b;
 81         }
 82     }
 83     return a;
 84 }
 85 bool check(node x,node y)
 86 {
 87     if(x.len>y.len)return 1;
 88     if(x.len<y.len)return 0;
 89     bool bz=0;
 90     for(int i=x.len-1;i>=0;i--)
 91     {
 92         if(x.s[i]>y.s[i]){bz=1;break;}
 93         if(x.s[i]<y.s[i]){bz=0;break;}
 94     }
 95     return bz;
 96 }
 97 void init()
 98 {
 99     a[1].s[a[1].len++]=1;
100     a[2].s[a[2].len++]=1;
101 }
102 int main()
103 {
104     init();
105     for(int i=3;i<=2000;i++)
106     {        
107         a[i]=sum(a[i-1],a[i-2]);
108     }
109     for(scanf("%d",&t);t--;)
110     {
111         scanf("%d",&n);
112         m.read();
113         for(int i=1;i<=2000;i++)
114         {
115             if(check(a[i],sum(m,a[1])))
116             {
117                 ans=del(m,a[i-2]);
118                 break;
119             }
120         }
121         printf("%d\n",modit(ans));
122     }
123 }
View Code

 

posted @ 2020-08-12 17:21  HYDcn666_JZOJ  阅读(73)  评论(0编辑  收藏  举报