HDU4099(斐波那契数列与字典树)

题目:Revenge of Fibonacci

 

题意:给出斐波那契数列的前k位,k不超过40,找出最小的正整数n,满足F(n)的前k位与给定数的前k位相同,斐波那契数列的项数不超过100000。

 

解析:本题可以分为两步:

第一步就是预处理出100000项斐波那契数列的前40位,插入到字典树中。

第二步就是查询匹配求最小的n。

对于第一步,我们可以把斐波那契数列精确到50多位,然后只存40位即可,这样就防止进位的误差。在斐波那契数列加法过程中,我们只把它的前50多

位进行相加,不然存不下。

 

#include <iostream>

#include <string.h>

#include <stdio.h>



using namespace std;

const int N=10;



int f1[65],f2[65],f3[65];



class Trie

{

    public:

       int v;

       int flag;

       Trie *next[N];

       Trie()

       {

           v=-1;

           memset(next,NULL,sizeof(next));

       }

};



Trie *root;



void Insert(char *S,int ans)

{

    int len=strlen(S);

    Trie *p=root;

    for(int i=0;i<len;i++)

    {

        int id=S[i]-'0';

        if(p->next[id]==NULL)

            p->next[id]=new Trie();

        p=p->next[id];

        if(p->v<0) p->v=ans;

    }

}



int Find(char *S)

{

    Trie *p=root;

    int count;

    int len=strlen(S);

    for(int i=0;i<len;i++)

    {

        int id=S[i]-'0';

        p=p->next[id];

        if(p==NULL) return -1;

        else  count=p->v;

    }

    return count;

}



void Init()

{

    int h;

    char str[65]="1";

    memset(f1,0,sizeof(f1));

    memset(f2,0,sizeof(f2));

    memset(f3,0,sizeof(f3));

    f1[0]=1;f2[0]=1;

    Insert(str,0);

    for(int i=2;i<100000;i++)

    {

        memset(str,0,sizeof(str));

        int r=0;

        for(int j=0;j<60;j++)

        {

            f3[j]=f1[j]+f2[j]+r;

            r=f3[j]/10;

            f3[j]%=10;

        }

        for(int j=59;j>=0;j--)

        if(f3[j])

        {

            h=j;

            break;

        }

        int k=0;

        for(int j=h;j>=0;j--)

        {

            str[k++]=f3[j]+'0';

            if(k>=40) break;

        }

        Insert(str,i);

        if(h>55)

        {

            for(int j=1;j<59;j++)

                f3[j-1]=f3[j];

            for(int j=1;j<59;j++)

                f2[j-1]=f2[j];

        }

        for(int j=0;j<60;j++)

            f1[j]=f2[j];

        for(int j=0;j<60;j++)

            f2[j]=f3[j];

    }

}



int main()

{

    root=new Trie();

    Init();

    char str[105];

    int t,i,j,k=1;

    scanf("%d",&t);

    while(t--)

    {

        scanf("%s",str);

        printf("Case #%d: ",k++);

        int tmp=Find(str);

        printf("%d\n",tmp);

    }

    return 0;

}


 

 

你可能感兴趣的:(HDU)