hdu 4099 Revenge of Fibonacci Trie树与模拟数位加法

Revenge of Fibonacci

题意:给定fibonacci数列的前100000项的前n位(n<=40);问你这是fibonacci数列第几项的前缀?如若不在前100000项范围内,输出-1;

思路:直接使用数组模拟加法,再用Trie树插入查找即可;但是一般使用new Trie()的代码都是MLE的。反而我之前写的,直接得到数组大小的maxnode版本的内存可以接受;并且还有一点就是前40位的精度问题;由于是自己计算出来的finboncci数列,并不是系统给的,所以1的进位不会形成很长序列的递推,但是也不能只计算到40+位..代码中是计算到了前60位,然后只往Trie中传了40位,还有一点就是要维护前60位的值,即当位数增加时,逐渐地将末位舍去;

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<vector>
#include<cmath>
#include<stdlib.h>
#include<time.h>
#include<stack>
#include<set>
#include<map>
#include<queue>
using namespace std;
#define rep0(i,l,r) for(int i = (l);i < (r);i++)
#define rep1(i,l,r) for(int i = (l);i <= (r);i++)
#define rep_0(i,r,l) for(int i = (r);i > (l);i--)
#define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
#define MS0(a) memset(a,0,sizeof(a))
#define MS1(a) memset(a,-1,sizeof(a))
#define MSi(a) memset(a,0x3f,sizeof(a))
#define inf 0x3f3f3f3f
#define lson l, m, rt << 1
#define rson m+1, r, rt << 1|1
typedef pair<int,int> PII;
#define A first
#define B second
#define MK make_pair
typedef __int64 ll;
template<typename T>
void read1(T &m)
{
    T x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    m = x*f;
}
template<typename T>
void read2(T &a,T &b){read1(a);read1(b);}
template<typename T>
void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);}
template<typename T>
void out(T a)
{
    if(a>9) out(a/10);
    putchar(a%10+'0');
}
const int maxl = 1e5*45 + 7;
const int sigma_size = 10;
struct Trie{
    int val[maxl],sz;
    int ch[maxl][10];
    Trie(){sz = 1;MS0(ch[0]);}
    void Insert(char *s,int v)
    {
        int u = 0,len = strlen(s);
        rep0(i,0,len){
            int c = s[i]-'0';
            if(ch[u][c] == 0){
                MS0(ch[sz]);
                val[sz] = v;
                ch[u][c] = sz++;               
            }
            u = ch[u][c];
        }
        if(val[u] == 0) val[u] = v;//不能直接覆盖;
    }
    int Find(char *s)
    {
        int u = 0,len = strlen(s);
        rep0(i,0,len){
            int c = s[i]-'0';
            if(ch[u][c] == 0) return 0;
            u = ch[u][c];
        }
        return val[u];
    }
}trie;
int a[60],b[60],c[60];
void init()
{
    char s[60] = {'1'};
    a[0] = 1;b[0] = 1;
    trie.Insert(s,1);
    rep0(i,2,100000){
        int r = 0,cnt = 0;
        rep1(j,0,60){
            c[j] = a[j]+b[j]+r;
            r = c[j]/10;
            c[j] = c[j]%10;
        }
        int id = -1;
        rep_1(j,60,0){
            if(id < 0 && c[j]) id = j;
            if(~id){
                s[cnt++] = c[j]+'0';
            }
            if(cnt >= 40) break;
        }
        s[cnt] = '\0';
        trie.Insert(s,i+1);
        if(id >= 55){ //防止进位误差,舍去后面一位;
            rep1(j,1,60)
                c[j-1] = c[j],b[j-1] = b[j];
            c[60] = b[60] = 0;
        }
        rep1(j,0,60){
            a[j] = b[j];
            b[j] = c[j];
        }
    }
}
int main()
{
    init();
    int kase = 1,T;
    read1(T);
    char str[45];
    while(T--){
        scanf("%s",str);
        printf("Case #%d: %d\n",kase++,trie.Find(str)-1);
    }
    return 0;
}

 

你可能感兴趣的:(hdu 4099 Revenge of Fibonacci Trie树与模拟数位加法)