UVa 12333 - Revenge of Fibonacci(字典树+高精度压位)

输入一个斐波那契数的前缀,求开头与所给前缀相同的最小斐波那契数的编号。

容易超时的一道题,计算前十万个斐波那契数要用高精度算法,还要注意只保留前50位就够了,不然会超时。

然后就是查询,原本保存在string数组中,单次查找复杂度为O(n*s.length())。发现查找会超时,后来使用了字典树,单次查找仅为O(s.length()),效率提高很多,就过了。

建树使用了指针,调用之前一定要判断不为空。

#include<iostream>
#include<vector>
#include<string>
using namespace std;
vector<int>a[3];
struct Node{
    int num;
    bool have_value;
    Node* p[10];
    Node(int num=0):num(num),have_value(false){}
};
Node* root;
Node* newnode(){
    Node* temp;
    temp=new Node();
    for(int i=0;i<10;temp->p[i++]=NULL);
    return temp;
}
string Sum(int x){//求前十万个斐波那契数。
    string s0;
    a[x%3]=a[(x-1)%3];
    if(a[(x-1)%3].size()!=a[(x-2)%3].size())
        for(int i=1;i<(int)a[(x-1)%3].size();i++)
            a[x%3][i]+=a[(x-2)%3][i-1];
    else for(int i=0;i<(int)a[(x-1)%3].size();i++)
        a[x%3][i]+=a[(x-2)%3][i];
    for(int i=(int)a[x%3].size()-1;i>0;i--){
        a[x%3][i-1]+=a[x%3][i]/10;
        a[x%3][i]%=10;
    }
    while(a[x%3][0]>9){
        a[x%3].insert(a[x%3].begin(),a[x%3][0]/10);
        a[x%3][1]%=10;
    }
    for(int i=0;i<a[x%3].size();s0+=a[x%3][i++]+'0');
    while(a[x%3].size()>50&&a[(x-1)%3].size()>50){
        a[x%3].erase(a[x%3].end()-1);
        a[(x-1)%3].erase(a[(x-1)%3].end()-1);
    }
    return s0;
}
void build(Node* u,string s,int k){//建树。
    for(int i=0;i<s.length();i++){
        int t=s[i]-'0';
        if(u->p[t]==NULL) u->p[t]=newnode();
        if(!u->p[t]->have_value){
            u->p[t]->have_value=true;
            u->p[t]->num=k;
        }
        u=u->p[t];
    }
    return;
}
int search(string s,Node* b){//字典树查找。
    for(int i=0;i<s.length();i++){
        if(b->p[s[i]-'0']==NULL) return -1;
        b=b->p[s[i]-'0'];
    }
    if(!b->have_value) return -1;//指针未赋值,返回-1。
    return b->num;
}
int main(){
    a[0].push_back(1);
    a[1].push_back(1);
    root=newnode();
    root->p[1]=newnode();
    root->p[1]->have_value=true;
    for(int i=2;i<100000;i++)
        build(root,Sum(i),i);
    int n,t=0;
    cin>>n;
    while(n--){
        string s0;
        cin>>s0;
        cout<<"Case #"<<++t<<": "<<search(s0,root)<<endl;
    }
    return 0;
}

你可能感兴趣的:(uva)