hdu 4099 Revenge of Fibonacci 字典树+斐波拉契数列数列

来源:互联网 发布:网络系统图的 编辑:程序博客网 时间:2024/05/18 13:27

题意:给你N个数,让你查找是不是前100000个斐波拉契数列的前40位,如果是,那就输出下标最小的那个斐波拉契数列数列的下标。

解析:主要是通过trie树来进行,插入和查询,即将前100000个斐波拉契数和下标插入trie树中,然后通过查询输出下标即可(个别细节自己考虑下),现在的关键是如何插入100000个斐波拉契数列(只要前40位),准确的是怎么求这么大的数据(详细见Numinit()函数),注意进位。

#include<cstdio>#include<cstring>#include<string>#include<algorithm>using namespace std;const int maxn=5200009;struct trie{    int next[12];    int id;    void init()    {        id=-1;        memset(next,0,sizeof(next));    }}tree[maxn];int index;void insert(char *s,int id){   //printf("%s %d\n",s,id);    int len=strlen(s);    int p=0;    for(int i=0;i<len;i++)    {        int x=s[i]-'0';        if(tree[p].next[x]==0)          {              tree[index+1].init();              tree[p].next[x]=++index;          }          p=tree[p].next[x];          if(tree[p].id==-1)           tree[p].id=id;    }}int find(char *s){    int len=strlen(s);    int p=0;    int x;    int i;    for(i=0;i<len;i++)    {        x=s[i]-'0';        if(tree[p].next[x]==0)        break;        p=tree[p].next[x];        //printf("%d\n",tree[p].id);    }    if(s[i]!='\0')    return -1;    return tree[p].id;}char a[65],b[65],c[65];void Numinit(){    memset(a,'0',sizeof(a));    memset(b,'0',sizeof(b));    memset(c,'0',sizeof(c));    a[0]='1',a[1]='\0',b[0]='1',b[1]='\0';    int t=0,num=2;    insert(a,t++);    insert(b,t++);    a[1]='0',b[1]='0';    //printf("%c %c %c %c\n",a[0],a[1],b[0],b[1]);    while(num<100000)    {        for(int i=0;i<64;i++)        {         if(a[i]+b[i]+c[i]-'0'-'0'-'0'>9)//判断是不是需要进位         {             c[i+1]+=1;             c[i]+=a[i]+b[i]-10-'0'-'0';         }         else         {             c[i]+=a[i]+b[i]-'0'-'0';         }         //printf("%c %c %c\n",a[i],b[i],c[i]);        }        int breaknum;        for(int i=64;i>=0;i--)        {            if(c[i]>='1'&&c[i]<='9')            {                breaknum=i;                break;            }        }        if(breaknum>55)//保留前55位,防止40位时进位越界        {            for(int i=0;i<63;i++)//数据是倒着存的             b[i]=b[i+1],c[i]=c[i+1];             breaknum--;        }        char str[65];        int i;        for(i=0;i<65;i++)//保留40位        {            str[i]=c[breaknum--];            if(i==39)            break;            if(breaknum==-1)            break;        }        str[i+1]='\0';        //if(num==20)  break;        //printf("%s\n",str);        insert(str,t++);//将数插入trie树        strcpy(a,b);//交换,a,b,c        strcpy(b,c);        memset(c,'0',sizeof(c));//注意,每次都要初始化        num++;//下一个数    }}int main(){   index=0;    tree[0].init();    Numinit();    int cases;    char ss[65];    scanf("%d",&cases);    for(int i=1;i<=cases;i++)    {        scanf("%s",ss);        printf("Case #%d: %d\n",i,find(ss));    }    return 0;}


0 0