题目链接:
http://poj.org/problem?id=2413
题目大意:
定义fibonacci数列前两项f[1] = 1,f[2] = 2。现在给你一个区间[a,b],a <= b <= 10^100。
问:区间[a,b]之间有多少个fibonacci数。
思路:
a、b的规模很大,是个100位10进制的数。所以要用数组模拟大整数加法求fibonacci数列。用整型
二维数组F[i][]表示第i个fibonacci数,因为从个位倒着存入数组方便进位,所以F[i][]数组中的数是倒
着的。第480个fibonacci数是101位,先求出前480个fibonacci数,然后清除前导零,将结果存入二
维字符串数组Fi[][]中。因为a、b很大,用字符串村村a、b,然后用二分查找找到a、b的位置。如果
找到的位置不是fibonacci数时,返回第一个比它大的fibonacci数位置。最后标记下b是否为fibonacci
数。如果b为fibonacci数,则答案为 b的位置 - a的位置 + 1,如果b不为fibonacci数,则答案为
b的位置 - a的位置。
AC代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 550;
const int MAXNLEN = 130;
int F[MAXN][MAXNLEN];
char Fi[MAXN][MAXNLEN],ans[MAXN];
void Fibo()
{
F[1][0] = 1;
F[2][0] = 2;
for(int i = 3; i <= 500; ++i)
{
for(int j = 0; j <= 110; ++j)
{
F[i][j] = F[i][j] + F[i-1][j] + F[i-2][j];
if(F[i][j] >= 10)
{
F[i][j+1] += F[i][j]/10;
F[i][j] %= 10;
}
}
}
for(int i = 1; i <= 500; ++i)
{
int j;
for(j = 110; j >= 0; j--)
if(F[i][j] == 0)
continue;
else
break;
int k = 0;
for(; j >= 0; j--)
Fi[i][k++] = F[i][j] + '0';
F[i][k] = '\0';
}
// for(int i = 1; i <= 50; ++i)
// {
// for(int j = 0; j < strlen(Fi[i]); j++)
// printf("%c",Fi[i][j]);
// printf("\n");
// }
}
int cmp(char *A,char *B)
{
int LenA = strlen(A);
int LenB = strlen(B);
if(LenA != LenB)
return LenA > LenB ? 1 : -1;
else
return strcmp(A,B);
}
int Search(char *Num,bool &flag)
{
int low = 1;
int high = 480;
while(low <= high)
{
int mid = (low+high)/2;
int res = cmp(Num,Fi[mid]);
if(res == 0)
{
flag = 1;
return mid;
}
else if(res < 0)
high = mid - 1;
else
low = mid + 1;
}
return low;
}
char A[MAXNLEN],B[MAXNLEN];
int main()
{
Fibo();
while(~scanf("%s %s",A,B))
{
if(strcmp(A,"0")==0 && strcmp(B,"0") == 0)
break;
bool FlagA = 0;
bool FlagB = 0;
int Left = Search(A,FlagA);
int Right = Search(B,FlagB);
if(FlagB)
printf("%d\n",Right-Left+1);
else
printf("%d\n",Right-Left);
}
return 0;
}