求一个数是第几个斐波那契数的前缀,如果是多个斐波那契数的前缀,则输出最小的那一个。
因为前缀最多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;
}