HDU 4099 字典树+高精度

题意:给出某项斐波那契数的前几位,让输出最小的一项前缀为这个串的项数。

先高精度算出前100000项斐波那契的前50位。并把前40位存进字典树预处理一下。字典树节点值存为第几项。然后输入字符串直接查找。

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 50
int fib[3][N+1];
class trie
{
public:
    trie* next[10];
    int value;
    trie()
    {
        for(int i=0; i<10; i++)
            next[i]=0;
        value=-1;
    }
} root,*a;
void insert(trie* p,int* s,int n,int len)
{
    p=&root;
    int k=len;
    while(k>=0&&len-k<=40)
    {
        if(!p->next[s[k]])
            p->next[s[k]]=new trie;
        p=p->next[s[k]];
        if(p->value==-1)
            p->value=n;
        k--;
    }
}
int find(trie* p,char* s)
{
    p=&root;
    int k=0,ans;
    while(s[k]!='\0')
    {
        if(!p->next[s[k]-'0'])
            return -1;
        p=p->next[s[k]-'0'];
        k++;
    }
    return p->value;
}
void init()
{
    memset(fib,0,sizeof(fib));
    char str[45];
    fib[0][0]=1;
    fib[1][0]=1;
    insert(a,fib[0],0,0);
    int i,j;
    for(i=2; i<100000; i++)
    {
        int c=0;
        for(j=0; j<=N; j++)
        {
            fib[2][j]=(c+fib[1][j]+fib[0][j])%10;
            c=(c+fib[1][j]+fib[0][j])/10;
        }
        if(j==N+1&&c>0)
        {
            for(int t=0; t<N; t++)
            {
                fib[0][t]=fib[1][t+1];
                fib[1][t]=fib[2][t+1];
            }
            fib[0][N]=0;
            fib[1][N]=c;
        }
        else
        {
            for(int t=0; t<=N; t++)
            {
                fib[0][t]=fib[1][t];
                fib[1][t]=fib[2][t];
            }
        }
        int t;
        for(t=N; t>=0; t--)
            if(fib[1][t]) break;
        insert(a,fib[1],i,t);
    }
}
int main()
{
    init();
    char temp[45];
    int t,ca=0;
    scanf("%d",&t);
    while(t--)
        scanf("%s",temp),
        printf("Case #%d: %d\n",++ca,find(a,temp));
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值