HDU 5351 MZL's Border(找规律+高精度)

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


Problem Description
As is known to all, MZL is an extraordinarily lovely girl. One day, MZL was playing with her favorite data structure, strings.

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=fibi1fibi2, 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[ni+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  1T100, 1n103, 1m|fibn| .
 

Input
The first line of the input is a number  T , which means the number of test cases.

Then for the following  T  lines, each has two positive integers  n  and  m , whose meanings are described in the description.
 

Output
The output consists of  T  lines. Each has one number, meaning  fibn 's  LBorderm  modulo  258280327(=2×317+1) .
 

Sample Input
  
  
2 4 3 5 5
 

Sample Output
  
  
1 2
 

Source
 

题目大意:一个按照类似斐波那契数变化的字符串,对于给定的第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;
}











基于bert实现关系三元组抽取python源码+数据集+项目说明.zip基于bert实现关系三元组抽取python源码+数据集+项目说明.zip基于bert实现关系三元组抽取python源码+数据集+项目说明.zip基于bert实现关系三元组抽取python源码+数据集+项目说明.zip基于bert实现关系三元组抽取python源码+数据集+项目说明.zip 个人大四的毕业设计、课程设计、作业、经导师指导并认可通过的高分设计项目,评审平均分达96.5分。主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 [资源说明] 不懂运行,下载完可以私聊问,可远程教学 该资源内项目源码是个人的毕设或者课设、作业,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96.5分,放心下载使用! 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),供学习参考。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值