hdu 4099 Revenge of Fibonacci 大数+压位+trie

最近手感有点差,所以做点水题来锻炼一下信心。

下周的南京区域赛估计就是我的退役赛了,bless all。

 

Revenge of Fibonacci

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 204800/204800 K (Java/Others)
Total Submission(s): 1582    Accepted Submission(s): 356


Problem Description
The well-known Fibonacci sequence is defined as following:


  Here we regard n as the index of the Fibonacci number F(n).
  This sequence has been studied since the publication of Fibonacci's book Liber Abaci. So far, many properties of this sequence have been introduced.
  You had been interested in this sequence, while after reading lots of papers about it. You think there’s no need to research in it anymore because of the lack of its unrevealed properties. Yesterday, you decided to study some other sequences like Lucas sequence instead.
  Fibonacci came into your dream last night. “Stupid human beings. Lots of important properties of Fibonacci sequence have not been studied by anyone, for example, from the Fibonacci number 347746739…”
  You woke up and couldn’t remember the whole number except the first few digits Fibonacci told you. You decided to write a program to find this number out in order to continue your research on Fibonacci sequence.
 

 

Input
  There are multiple test cases. The first line of input contains a single integer T denoting the number of test cases (T<=50000).
  For each test case, there is a single line containing one non-empty string made up of at most 40 digits. And there won’t be any unnecessary leading zeroes.
 

 

Output
  For each test case, output the smallest index of the smallest Fibonacci number whose decimal notation begins with the given digits. If no Fibonacci number with index smaller than 100000 satisfy that condition, output -1 instead – you think what Fibonacci wants to told you beyonds your ability.
 
 

分析:

  刚刚搜了一下,发现大家的做法都是直接存取高位前50位,这题能过。但是对于这种数据:1,9...9的话就无能为力了吧 - -

  所以我们比赛时的做法是:我们用java试了一下10w时的斐波那契数,长度大概为2w多。因此我们用大数做,用C++压了10位,那么最大的数的长度大概为2000多,复杂度也就O(n*n)。然后对于前40个存到trie里面,只有当创建节点时才更新信息。

 

#include <set>

#include <map>

#include <list>

#include <cmath>

#include <queue>

#include <stack>

#include <string>

#include <vector>

#include <cstdio>

#include <cstring>

#include <complex>

#include <iostream>

#include <algorithm>



using namespace std;



typedef long long ll;

typedef unsigned long long ull;



#define debug puts("here")

#define rep(i,n) for(int i=0;i<n;i++)

#define rep1(i,n) for(int i=1;i<=n;i++)

#define REP(i,a,b) for(int i=a;i<=b;i++)

#define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)

#define pb push_back

#define RD(n) scanf("%d",&n)

#define RD2(x,y) scanf("%d%d",&x,&y)

#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)

#define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)

#define All(vec) vec.begin(),vec.end()

#define MP make_pair

#define PII pair<int,int>

#define PQ priority_queue

#define cmax(x,y) x = max(x,y)

#define cmin(x,y) x = min(x,y)

#define Clear(x) memset(x,0,sizeof(x))

#define lson rt<<1

#define rson rt<<1|1

#define SZ(x) x.size()



/*



#pragma comment(linker, "/STACK:1024000000,1024000000")



int ssize = 256 << 20; // 256MB

char *ppp = (char*)malloc(ssize) + ssize;

__asm__("movl %0, %%esp\n" :: "r"(ppp) );



*/



char IN;

bool NEG;

inline void Int(int &x){

    NEG = 0;

    while(!isdigit(IN=getchar()))

        if(IN=='-')NEG = 1;

    x = IN-'0';

    while(isdigit(IN=getchar()))

        x = x*10+IN-'0';

    if(NEG)x = -x;

}

inline void LL(ll &x){

    NEG = 0;

    while(!isdigit(IN=getchar()))

        if(IN=='-')NEG = 1;

    x = IN-'0';

    while(isdigit(IN=getchar()))

        x = x*10+IN-'0';

    if(NEG)x = -x;

}



/******** program ********************/



const int MAXN = 2500;

const int kind = 10;

const ll INF = 1e10;



char s[50];



struct node{

    node *ch[kind];

    int id;



    node(){

        Clear(ch);

        id = -1;

    }

    node(int _id):id(_id){

        Clear(ch);

    }

}*rt;



struct Big{ // 大数,压了十位

    ll a[MAXN];

    int len;



    Big(){

        Clear(a);

        len = 0;

    }



    void add(Big now){ // this > now

        int in = 0;

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

            a[i] += now.a[i]+in;

            if(a[i]>=INF){

                in = 1;

                a[i] -= INF;

            }else in = 0;

        }

        if(in)a[len++] = in;

    }

    void out(){

        for(int i=len-1;i>=0;i--)

            cout<<a[i]<<" ";

        cout<<endl;

    }

}a,b,c;



int p[52],len;



void ins(node *root,int id){ // 插入到trie

    rep(i,len){

        int c = p[i];

        if(root->ch[c]==NULL)

            root->ch[c] = new node(id);

        root = root->ch[c];

    }

}



void cal(){ // 把当前的大数前40位取出

    len = 0;

    int top = a.len-1;

    ll now = a.a[top];



    while(now){

        p[len++] = now%10;

        now /= 10;

    }

    reverse(p,p+len);



    for(int i=top-1;i>=0;i--){

        now = a.a[i];

        int t = len;

        for(int j=0;j<10;j++){

            p[len++] = now%10;

            now /= 10;

        }

        reverse(p+t,p+len);

        if(len>=40)break;

    }

    cmin(len,40);

}



void init(){ // 预处理出前10w个, 存到trie中

    Clear(a.a);

    a.a[0] = a.len = 1;



    Clear(b.a);

    b.len = 0;



    p[0] = len = 1;

    ins(rt,0);



    for(int i=1;i<100000;i++){

        c = a;

        a.add(b);



        b = c;

        cal();

        ins(rt,i);

    }

}



int ask(node *root){ // 询问

    scanf("%s",s);

    for(int i=0;s[i];i++){

        int now = s[i]-'0';

        if(root->ch[now]==NULL)

            return -1;

        root = root->ch[now];

    }

    return root->id;

}



int main(){



#ifndef ONLINE_JUDGE

    freopen("sum.in","r",stdin);

    //freopen("sum.out","w",stdout);

#endif



    rt = new node();

    init();

    int ncase,Ncase = 0;

    RD(ncase);

    while(ncase--)

        printf("Case #%d: %d\n",++Ncase,ask(rt));



    return 0;

}

  

你可能感兴趣的:(fibonacci)