hdu 4099 Revenge of Fibonacci 2011 Asia Shanghai Regional Contest

求一个数是第几个斐波那契数的前缀,如果是多个斐波那契数的前缀,则输出最小的那一个。

因为前缀最多40个,所以只需求出每个斐波那契数的前60位(防止进位误差),用字典树保存前缀。

#include<iostream>
#include<cstring>

using namespace std;

struct dictree
{
 struct dictree * child[10];
 int ID;
}*root;

int a[3][61];
char ask[45];

void add(int *a,int *b,int *ans);
void update(int *num,int k);
int search(char * str);

int main()
{
 int t;
 int count=1;
 a[1][0]=0;
 a[2][0]=1;

 root=new struct dictree;
 for(int i=0;i<10;i++)
  root->child[i]=NULL;
 root->ID=-1;

 for(i=3;i<=100000;i++)
 {
  memset(a[i%3],0,sizeof(a[i%3]));
  add(a[(i+1)%3],a[(i+2)%3],a[i%3]);

/*  int ok=60;
  while(a[i%3][ok]<=0)
   ok--;

  cout<<i-2<<":  ";
  for(int j=ok;j>=0;j--)
   cout<<a[i%3][j];
  cout<<endl;*/

  update(a[i%3],i-2);
 }

 cin>>t;
 while(t--)
 {
  cin>>ask;
  cout<<"Case #"<<count++<<": ";

  if(ask[0]=='1' && strlen(ask)==1)
   cout<<0<<endl;
  else
   cout<<search(ask)<<endl;
 }


 return 0;
}

void add(int *a,int *b,int *ans)
{
 int temp=0;
 int ta,tb;
 int t[61]={0};

 int z=60,y=60;
 while(a[z]<=0)
  z--;
 ta=a[z];
 while(a[y]<=0)
  y--;
 tb=b[y];

 if(y<60 || (y==60 && z<60) )
 {
  for(int i=0;i<=60;i++)
  {
   t[i]=a[i]+b[i]+temp;
   temp=t[i]/10;
   t[i]%=10;
  }

  for(i=60;i>=0;i--)
  {
   if(t[i]>0)
    break;
  }

  if(temp>0)
  {
   for(int k=0;k<=i-1;k++)
    ans[k]=t[k+1];
   ans[i]=temp;
  }
  else
   for(int k=0;k<=i;k++)
    ans[k]=t[k];
 }
 else
 {
  if(ta>tb)
  {
   for(int i=0;i<=59;i++)
   {
    t[i]=a[i+1]+b[i]+temp;
    temp=t[i]/10;
    t[i]%=10;
   }

   t[60]=b[60]+temp;
   temp=t[60]/10;
   t[60]%=10;
  }
  else
  {
   for(int i=0;i<=60;i++)
   {
    t[i]=a[i]+b[i]+temp;
    temp=t[i]/10;
    t[i]%=10;
   }
  }

  

  if(temp>0)
  {
   for(int k=0;k<=59;k++)
    ans[k]=t[k+1];
   ans[60]=temp;
  }
  else
   for(int k=0;k<=60;k++)
    ans[k]=t[k];
 }
}

void update(int *num,int k)
{
 struct dictree * now,*newnode;

 now=root;

 int q=60;

 while(num[q]==0)
  q--;

 for(int i=q;i>=0 && q-i<40;i--)
 {
  if(now->child[num[i]]!=NULL)
  {
   now=now->child[num[i]];
  }
  else
  {
   newnode=new struct dictree;
   for(int j=0;j<10;j++)
   {
    newnode->child[j]=NULL;
   }
   newnode->ID=k;

   now->child[num[i]]=newnode;

   now=newnode;
  }
 }
 if(k<now->ID || now->ID==-1)
  now->ID=k;
}

int search(char * str)
{
 struct dictree * now;
 int len=strlen(str);

 now=root;

 for(int i=0;i<len && i<40;i++)
 {
  if(now->child[str[i]-'0']!=NULL)
   now=now->child[str[i]-'0'];
  else
   return -1;
 }
 return now->ID;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值