标签:
题目链接:
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; }
标签:
原文地址:http://blog.csdn.net/lianai911/article/details/45110427