紫书第五章习题 5-15 UVa 12333 - Revenge of Fibonacci

出处:https://blog.csdn.net/mobius_strip/article/details/27053639

题目链接:https://vjudge.net/contest/231030#problem/O


题目:给你一个数字串,判断他是哪一个Fib数的前缀,有多种答案输出最小的,不存在输出-1。

分析:字符串,大整数。

            首先,利用大整数计算Fib的前100000项,由于数据较大,只储存前50位即可。

            然后,按Fib的顺序存入字典树,利用滚动数组一边生成一边存储,可以减少内存开销。

                        在存的过程中直接进行标记,每个新节点直接标记成新加入的编号即标记路径。

                        这个值就表示到这个点结束的最小编号,这显然成立。

                        如果有更小的编号,应该更早早插入;而后面相同前缀的编号一定更大。

            最后,读入字符换,查询即可,无论是否是单词节点,直接返回记录的编号即可。


#include <iostream>  
#include <cstdlib>  
#include <cstring>  
#include <cstdio>  
  
using namespace std;  
  
/* Trie define */    
#define nodesize 4000004      //节点个数     
#define dictsize 10           //字符集大小     
    
typedef struct node1    
{  
    int    id;  
    int    flag;            //值域     
    node1* next[dictsize];    
}tnode;    
tnode  dict[nodesize];    
int    ID[256];  
    
class Trie    
{    
    private:  
        int    size;    
        tnode* root;    
    public:    
        Trie() {makeID(); initial();}    
        void makeID() {    
            for ( int i = 0 ; i < 10 ; ++ i )    
                ID['0'+i] = i;  
        }    
        void initial() {    
            memset( dict, 0, sizeof( dict ) );    
            root=NULL; size=0; root=newnode();    
        }    
        tnode* newnode() {return &dict[size ++];}    
        void insert( char* word, int L, int id ) {    
            tnode* now = root;    
            for ( int i = 0 ; i < L ; ++ i ) {  
                if ( !now->next[ID[word[i]]] )    
                    now->next[ID[word[i]]] = newnode();    
                /* 标记路径 */  
                if ( !now->id && !now->flag ) now->id = id;  
                now = now->next[ID[word[i]]];    
            }  
            if ( !now->flag ) {  
                now->flag = 1;  
                now->id = id;  
            }  
        }  
        int query( char* word ) {  
            tnode* now = root;    
            for ( int i = 0 ; word[i] ; ++ i ) {  
                if ( !now->next[ID[word[i]]] ) return -1;    
                now = now->next[ID[word[i]]];    
            }  
            return now->id;  
        }  
}trie;    
/* Trie  end */    
  
int  F[2][21000];  
char FF[42],In[42];  
  
int main()  
{  
    /* 大整数计算Fib前100000个数字 */  
    memset( F, 0, sizeof(F) );  
    F[0][0] = F[1][0] = 1;  
    trie.insert( "1", 1, 0 );  
    int s = 0,l = 1,r,count,p,q;  
    for ( int i = 2 ; i < 100000 ; ++ i ) {  
        p = i%2, q = (i+1)%2;  
        for ( int j = s ; j < l ; ++ j )  
            F[p][j] = F[p][j] + F[q][j];  
        for ( int j = s ; j < l ; ++ j )  
            if ( F[p][j] >= 10 ) {  
                F[p][j+1] += 1;  
                F[p][j]   -= 10;  
            }  
        if ( F[p][l] ) l ++;  
        if ( l - s > 50 ) s ++;  
        r = l-1;  count = 0;  
        while ( r >= 0 && count < 40 )   
            FF[count ++] = F[p][r --] + '0';  
  
        trie.insert( FF, count, i );  
    }  
    int T;  
    while ( scanf("%d",&T) != EOF )   
    for ( int t = 1 ; t <= T ; ++ t ) {  
        scanf("%s",In);  
        printf("Case #%d: %d\n",t,trie.query( In ));  
    }  
    return 0;  
}  

猜你喜欢

转载自blog.csdn.net/JXUFE_ACMer/article/details/80457520