MZL's Border
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 895 Accepted Submission(s): 287
MZL is really like Fibonacci Sequence , so she defines Fibonacci Strings in the similar way. The definition of Fibonacci Strings is given below.
1) fib1=b
2) fib2=a
3) fibi=fibi−1fibi−2, i>2
For instance, fib3=ab, fib4=aba, fib5=abaab .
Assume that a string s whose length is n is s1s2s3...sn . Then sisi+1si+2si+3...sj is called as a substring of s , which is written as s[i:j] .
Assume that i<n . If s[1:i]=s[n−i+1:n] , then s[1:i] is called as a Border of s . In Borders of s , the longest Border is called as s ' LBorder . Moreover, s[1:i] 's LBorder is called as LBorderi .
Now you are given 2 numbers n and m . MZL wonders what LBorderm of fibn is. For the number can be very big, you should just output the number modulo 258280327(=2×317+1) .
Note that 1≤T≤100, 1≤n≤103, 1≤m≤|fibn| .
Then for the following T lines, each has two positive integers n and m , whose meanings are described in the description.
2 4 3 5 5
1 2
题目大意:一个按照类似斐波那契数变化的字符串,对于给定的第n个字符串的前m个字符,前缀和后缀相同的最大长
度,其中前缀和后缀不能是该字符串。比如:n=5时,fib5=abaab,当m=5时,前缀为ab,后缀为ab时,两者相同且
长度最大。
解题思路:
//打出m在400以内的答案,观察寻找规律
#include <cstdio>
#include <string>
using namespace std;
//f_s[1]储存对应的斐波那契字符串
//string类的字符长度是有限的,2^32
string f_s[40];
//判断前缀和后最相同的最大长度,处理过程从下标1开始
int judge(string a,int m)
{
int i,j,k;
int flag;
int flag2=0;
for(i=m-1;i>0;i--)
{
flag=0;
for(j=1;j<=i;j++)
{
if(a[i-j+1]==a[m-j+1])
continue;
else
{
flag=1;
break;
}
}
if(flag==0)
{
flag2=1;
break;
}
}
if(flag2)
return i;
return 0;
}
int main()
{
int i,j,k,t;
freopen("outout.txt","w",stdout);
//模拟并储存对应的斐波那契字符串
f_s[1]+='b';f_s[2]='a';
for(i=3;i<40;i++)
f_s[i]=f_s[i-1]+f_s[i-2];
//字符串最前面添加一个字符,使得对应的斐波那契字符串以下标1开始
f_s[14]='0'+f_s[14];
//对应的m与对应的最大长度Lm
for(i=1;i<f_s[14].size();i++)
printf("m=%3d Lm=%3d\n",i,judge(f_s[14],i));
/*
//第n个斐波那契字符串和它的长度L
for(i=1;i<40;i++)
printf("n=%d L=%d\n",i,f_s[i].size());
*/
return 0;
}
对于结果似乎只与m有关,因为对于给定的n,m是符合条件的,并且m直接影响结果。
m= 1 Lm= 0
m= 2 Lm= 0
m= 3 Lm= 1
m= 4 Lm= 1
m= 5 Lm= 2
m= 6 Lm= 3
m= 7 Lm= 2
m= 8 Lm= 3
m= 9 Lm= 4
m= 10 Lm= 5
m= 11 Lm= 6
m= 12 Lm= 4
m= 13 Lm= 5
m= 14 Lm= 6
m= 15 Lm= 7
m= 16 Lm= 8
m= 17 Lm= 9
m= 18 Lm= 10
m= 19 Lm= 11
m= 20 Lm= 7
m= 21 Lm= 8
m= 22 Lm= 9
m= 23 Lm= 10
m= 24 Lm= 11
m= 25 Lm= 12
m= 26 Lm= 13
m= 27 Lm= 14
m= 28 Lm= 15
m= 29 Lm= 16
m= 30 Lm= 17
m= 31 Lm= 18
m= 32 Lm= 19
m= 33 Lm= 12
m= 34 Lm= 13
m= 35 Lm= 14
m= 36 Lm= 15
m= 37 Lm= 16
m= 38 Lm= 17
m= 39 Lm= 18
m= 40 Lm= 19
m= 41 Lm= 20
m= 42 Lm= 21
m= 43 Lm= 22
m= 44 Lm= 23
m= 45 Lm= 24
m= 46 Lm= 25
m= 47 Lm= 26
m= 48 Lm= 27
m= 49 Lm= 28
m= 50 Lm= 29
m= 51 Lm= 30
m= 52 Lm= 31
m= 53 Lm= 32
m= 54 Lm= 20
m= 55 Lm= 21
m= 56 Lm= 22
m= 57 Lm= 23
m= 58 Lm= 24
m= 59 Lm= 25
m= 60 Lm= 26
m= 61 Lm= 27
m= 62 Lm= 28
m= 63 Lm= 29
m= 64 Lm= 30
m= 65 Lm= 31
m= 66 Lm= 32
m= 67 Lm= 33
m= 68 Lm= 34
m= 69 Lm= 35
m= 70 Lm= 36
m= 71 Lm= 37
m= 72 Lm= 38
m= 73 Lm= 39
m= 74 Lm= 40
m= 75 Lm= 41
m= 76 Lm= 42
m= 77 Lm= 43
m= 78 Lm= 44
m= 79 Lm= 45
m= 80 Lm= 46
m= 81 Lm= 47
m= 82 Lm= 48
m= 83 Lm= 49
m= 84 Lm= 50
m= 85 Lm= 51
m= 86 Lm= 52
m= 87 Lm= 53
m= 88 Lm= 33
m= 89 Lm= 34
m= 90 Lm= 35
m= 91 Lm= 36
m= 92 Lm= 37
m= 93 Lm= 38
m= 94 Lm= 39
m= 95 Lm= 40
…… ……
…… ……
对于m的递增,结果是有相应的变化的,而且是呈现分段的递增。
当我们提取一些关键的m值时:1,2,4,7,12,20,33,54,88;
与之对应的结果的值是:0,0,1,2, 4,7, 12,20,33;
对于m值这组数(1,2,4,7,12,20,33,54,88,……),我们可以发现它们符合通式:a[i]=a[i-1]+a[i-2]+1;
对于结果这组数(0,0,1,2, 4,7, 12,20,33,……),我们可以发现它们就是m的值右移两位。
那么对于给定的m,我们就可以得出结果,首先找到比m小,但是最接近m的数,并且是符合通式a[i]=a[i-1]+a[i-2]+1
的数f[x],则结果就是m-f[x]+f[x-2]。
而对于m-f[x]+f[x-2]的求解则要用到高精度运算,因为m是非常容易超long long的。
C++代码如下:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <sstream>
#include <fstream>
#include <limits.h>
#define debug "output for debug\n"
#define pi (acos(-1.0))
#define eps (1e-4)
#define inf (1<<28)
#define sqr(x) (x) * (x)
#define MAX 300
using namespace std;
typedef long long ll;
typedef unsigned long long ULL;
string f[1005];
string add(string str1,string str2)//预处理出f[i]
{
string str;
int len1=str1.length();
int len2=str2.length();
//前面补0,弄成长度相同
if(len1<len2)
{
for(int i=1;i<=len2-len1;i++)
str1="0"+str1;//str1前面补零;str1=str1+"0";str1后面补零
//cout<<"str1"<<str1<<endl;
}
else
{
for(int i=1;i<=len1-len2;i++)
str2="0"+str2;
//cout<<"str1"<<str1<<endl;
}
len1=str1.length();
int cf=0;
int temp;
for(int i=len1-1;i>=0;i--)
{
if(i==len1-1)
temp=str1[i]-'0'+str2[i]-'0'+cf+1;
else
temp=str1[i]-'0'+str2[i]-'0'+cf;
cf=temp/10;
temp%=10;
str=char(temp+'0')+str;
}
if(cf!=0) str=char(cf+'0')+str;
return str;
}
string add1(string str1,string str2)//高精度加法
{
string str;
int len1=str1.length();
int len2=str2.length();
//前面补0,弄成长度相同
if(len1<len2)
{
for(int i=1;i<=len2-len1;i++)
str1="0"+str1;//str1前面补零;str1=str1+"0";str1后面补零
//cout<<"str1"<<str1<<endl;
}
else
{
for(int i=1;i<=len1-len2;i++)
str2="0"+str2;
//cout<<"str1"<<str1<<endl;
}
len1=str1.length();
int cf=0;
int temp;
for(int i=len1-1;i>=0;i--)
{
temp=str1[i]-'0'+str2[i]-'0'+cf;
cf=temp/10;
temp%=10;
str=char(temp+'0')+str;
}
if(cf!=0) str=char(cf+'0')+str;
return str;
}
string minu(string str1,string str2)
{
string str,s;
int len1=str1.length();
int len2=str2.length();
//前面补0,弄成长度相同
if(len1<len2)
{
for(int i=1;i<=len2-len1;i++)
str1="0"+str1;//str1前面补零;str1=str1+"0";str1后面补零
//cout<<"str1"<<str1<<endl;
}
else
{
for(int i=1;i<=len1-len2;i++)
str2="0"+str2;
//cout<<"str1"<<str1<<endl;
}
len1=str1.length();
int cf=0;
int temp;
for(int i=len1-1;i>=0;i--)
{
temp=str1[i]-'0'-(str2[i]-'0')+cf;
if(temp<0)
{
temp+=10;
cf=-1;
}
else
cf=0;
str=char(temp+'0')+str;
}
int k;
for(k=0;str[k]=='0'&&k<str.size()-1;k++);
for(int i=k;i<str.size();i++)
{
s=s+str[i];
}
return s;
}
int main()
{
int i,j,k,t,n,x;
string m,sum;
f[1]="1",f[2]="2";
for(i=3;i<1005;i++)
f[i]=add(f[i-1],f[i-2]);
//scanf("%d",&n);
//cout<<f[n]<<endl;
scanf("%d",&t);
while(t--)
{
//scanf("%d%",&n);
cin>>n>>m;
if(m=="1")
{
printf("0\n");
continue;
}
if(m=="2")
{
printf("0\n");
continue;
}
for(i=1;i<1005;i++)
{
if(f[i].size()==m.size())
{
if(f[i]==m)
{
x=i;
break;
}
if(f[i]>m)
{
x=i-1;
break;
}
}
if(f[i].size()>m.size())
{
x=i-1;
break;
}
}
//printf("x=%d\n",x);
//cout<<f[x]<<endl;
//cout<<f[x-2]<<endl;
sum=add1(minu(m,f[x]),f[x-2]);
//cout<<sum<<endl;
k=sum.size();
//printf("k=%d\n",k);
ll p=1;
//printf("pow=%I64d\n",p);
ll ans=sum[k-1]-'0';
//printf("ans=%I64d\n",ans);
for(j=k-2;j>=0;j--)
{
p=(p*10)%258280327;
//printf("p=%I64d\n",p);
//printf("%c\n",sum[j]);
ll pp=sum[j]-'0';
//printf("p=%I64d\n",pp);
ans=(ans+pp*p)%258280327;
//printf("ans=%I64d\n",ans);
}
printf("%I64d\n",ans%258280327);
//cout<<ans%258280327<<endl;
}
return 0;
}