0
点赞
收藏
分享

微信扫一扫

POJ2413 How many Fibs?【高精度】【二分】


题目链接:

​​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;
}



举报

相关推荐

0 条评论