HDU 4099 Revenge of Fibonacci(字典树+大数加法)

题意:给你一串数,判断它是否是斐波那契数列前100000(不包括第100000项,WA了一次)项某一项的前缀。给你的数最多不超过40位。

思路:直接构造前100000项斐波那契数列的字典树是肯定超时的,并且我们只需要前40位。然而由于考虑到进位的问题,我们保存它的前60位,也就是说60位以后的进位我们就可以忽略不计了,但是只保存45位就会WA。

#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<string>
#include<queue>
#include<vector>
#include<map>
using namespace std;
const int mx=4000005;
const int inf=0x3f3f3f3f;
int num,cas;
int fa[50005],fb[50005];
struct node{
    int ch[mx][10];
    int v[mx];
    int sz;
    void add(int *ss,int ind,int len)
    {
     int u=0,n=len;
     for(int i=0;i<n;i++)
     {
      //cout<<ss[i];
      int id=ss[i];
      if(ch[u][id]==0)
      {
       ch[u][id]=sz;
       //cout<<sz<<endl;
       memset(ch[sz],0,sizeof(ch[sz]));
       sz++;
      }
      u=ch[u][id];
      if(v[u]==-1) v[u]=ind;
     }
     //cout<<endl;
     //cout<<sz<<endl;
     //cout<<ch[0][1]<<" "<<v[u]<<endl;
    }
    void find(char *s)
    {
     int u=0,n=strlen(s);
     for(int i=0;i<n;i++)
     {
      int id=s[i]-'0';
      if(ch[u][id]==0) {printf("Case #%d: -1\n",cas++);return;}
      u=ch[u][id];
      //cout<<id<<" "<<v[u]<<endl;
     }
     printf("Case #%d: %d\n",cas++,v[u]);
     }
     void init(){
     memset(ch[0],0,sizeof(ch[0]));
     memset(v,-1,sizeof(v));
     sz=1;
     int j,k,i;
     memset(fa,0,sizeof(fa));
     memset(fb,0,sizeof(fb));
     fa[50000]=1;
     fb[50000]=1;
     j=50000;k=50000;
     add(fa+50000,0,1);
     for(i=2;i<100000;i++)
     {
      if(i&1){
          for(int ii=k;ii>=j;ii--)
          {
           fa[ii]+=fb[ii];
           if(fa[ii]>9) {fa[ii-1]+=fa[ii]/10;fa[ii]=fa[ii]%10;}
          }
          if(fa[j-1]!=0) j--;
          if(k-j==60) k--;
          add(fa+j,i,min(k-j+1,40));
          //for(int z=j;z<=k;z++) cout<<fa[z];
          //cout<<endl;
      }
      else {
          for(int ii=k;ii>=j;ii--)
          {
           fb[ii]+=fa[ii];
           if(fb[ii]>9) {fb[ii-1]+=fb[ii]/10;fb[ii]=fb[ii]%10;}
          }
          if(fb[j-1]!=0) j--;
          if(k-j==60) k--;
          add(fb+j,i,min(k-j+1,40));
          //for(int z=j;z<=k;z++) cout<<fb[z];
          //cout<<endl;
      }
     }
    }
}a;
int main()
{
    //ios::sync
    int T;
    char s[65];
    a.init();
    while(scanf("%d",&T)!=EOF)
    {
        cas=1;
        while(T--)
        {
            scanf("%s",s);
            a.find(s);
        }
    }
return 0;
}

猜你喜欢

转载自blog.csdn.net/lsd20164388/article/details/78619459
今日推荐