How many Fibs?
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 11896 | Accepted: 4312 |
Description
Recall the definition of the Fibonacci numbers:
Given two numbers a and b, calculate how many Fibonacci numbers are in the range [a,b].
f1 := 1 f2 := 2 fn := fn-1 + fn-2 (n>=3)
Given two numbers a and b, calculate how many Fibonacci numbers are in the range [a,b].
Input
The input contains several test cases. Each test case consists of two non-negative integer numbers a and b. Input is terminated by a=b=0. Otherwise, a<=b<=10100. The numbers a and b are given with no superfluous leading zeros.
Output
For each test case output on a single line the number of Fibonacci numbers fi with a<=fi<=b.
Sample Input
10 100 1234567890 9876543210 0 0
Sample Output
5 4
//这道题的意思就是在a和b之间有多少个fib函数就可以到了
//10 100找到10位到100位之间的fib数 //这么大的输入输出肯定要用数组了 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string> #define MAXN 150 #define MAXF 1000 int first[MAXN]; int second[MAXN]; int firstweishu = 0; int secondweishu = 0; int ans = 0; int fibnum[MAXF][MAXN]; //存所有的fib数 int weishu[MAXF]; //存每个fib数占的位数 //#define max(a,b) (a) >=(b)?(a):(b) //WA了无数次,最后还是自己的find函数写的有问题, 因为需要考虑90 120这种情况,90不是fib数,120也不是,中间也没有fib数,因此90在找比它大的fib数的时候是找不到的 //因为在比较位数比它大的数,就应该设置findflag =1,然后比较和end的数,这个改了就可以了 //另外case也考虑了0982 9999这样的情况,但是应该是不会出现的 //FIb数生成还是没问题的 //find的思路是1 2, start是1,end是2,那就是要找到在1和2之间的数,start找到>=1的序列, end<=2的序列, start如果找到比它大的数,那还要check下这个数是否比end大 //如果比end大那说明这个区间肯定没有fib数 //end要找的是比它小的数,因此从最后一个和它同长度的比较起,如果位数比它短,那可以直接返回了,因为start有比较是否比end大,因为end这边不需要再比较了 //最终AC int max(int a,int b) { if (a >= b) { return a; } else { return b; } } int index = 3; char a[MAXN] = { '\0' }; char b[MAXN] = { '\0' }; void init() { int i = 0; int j = 0; for (i = 0; i < MAXN;i++) { first[i] = 0; second[i] = 0; } ans = 0; return; } void initmatrix() { int i = 0; int j = 0; for (i = 0; i < MAXN; i++) { a[i] = '\0'; b[i] = '\0'; } return; } void initfib() { int i = 0; int j = 0; for (i = 0; i < MAXF; i++) { weishu[i] = 0; for (j = 0; j < MAXN; j++) { fibnum[i][j] = 0; } } return; } int fib(int a) { return fib(a-1) + fib(a-2); } int strlength(char* s) { int size = 0; int findshuzi = 0; while ('\0' != *s) { size += 1; s += 1; } return size; } int strlengths(char* s) { int size = 0; int findshuzi = 0; while ('\0' != *s) { if (('0' == *s) && (0 == findshuzi)) { } else { size += 1; findshuzi = 1; } s += 1; } if (0 == size) size += 1;//防止0的情况 return size; } void parse() { int i = 0; int j = 0; firstweishu = strlength(a); secondweishu = strlength(b); i = firstweishu - 1; j = 0; while ('\0' != a[j]) { first[i] = a[j] - '0'; i -= 1; j += 1; } i = secondweishu - 1; j = 0; while ('\0' != b[j]) { second[i] = b[j] - '0'; i -= 1; j += 1; } firstweishu = strlengths(a); secondweishu = strlengths(b); return; } //获取105位以内的所有fib数 void getfib() { int c = 0; int jinwei = 0; int i = 0; int d = 0; index = 3; fibnum[1][0] = 1; fibnum[2][0] = 2; weishu[1] = 1; weishu[2] = 1; while (1) { c = max(weishu[index-2],weishu[index-1]); jinwei = 0; if (7 == index) { index = index; } //从低位开始加,有进位就要记住 for (i = 0; i < c;i++) { d = fibnum[index-2][i] + fibnum[index-1][i] + jinwei; jinwei = 0; if (d <= 9) { fibnum[index][i] = d; } else { fibnum[index][i] = d - 10; jinwei = 1; } } weishu[index] = c; //最后加过来,看是否有进位 if (jinwei>0) { fibnum[index][c] = jinwei; weishu[index] = c+1; } if (index>= 500) break; index += 1; } return; } int x = 0; /* 假设 存在的数 x 考察的区间为[a , b]需要注意的 又这么几种情况 a < b < x a < b = x a = b < x a = b = x x = a < b x < a = b x < a < b*/ int findnew(int s[], int n) { int k; for (int i = 0; i <= 498; i++) { if (weishu[i] < n) continue; if (weishu[i] == n) { int flag = 0; for (k = n - 1; k >= 0; k--) { if (fibnum[i][k] > s[k]) return i; else if (fibnum[i][k] == s[k]) continue; else { flag = 1; break; } } if (flag == 0) { x++; return i; } } if (weishu[i] > n) return i; } return 0; } int find(int type) //1-分析第一个数,2-分析第2个数 { int num = 0; int i = 0; int startindex = 0; int findflag = 0; int j = 0; int cmpindex = 0; int sameindex = 0; if (1 == type) { num = firstweishu; } else { num = secondweishu; } //查找位数从哪个开始 for (i = 1; i < index;i++) { if (1 == type) { if (num == weishu[i]) { startindex = i; //找到了,然后下面开始找index break; } } else { if ((num+1) == weishu[i]) //要多一位 { startindex = i-1; //找到了,然后下面开始找index break; } } } //start要找个比>=start的 if (1 == type) { while (1) { findflag = 0; if (firstweishu < weishu[startindex]) { findflag = 1; } else { //从startindex开始找起,从最高位开始比较 for (i = num - 1; i >= 0; i--) { if (fibnum[startindex][i] > first[i]) { findflag = 1; //找到大数 break; } else if (fibnum[startindex][i] == first[i]) //数字相同,那要继续比较 { if (i == 0) { findflag = 1; } else { continue; } } else { //比现在的数小,那就只能break break; } } } if (1 == findflag) { cmpindex = max(secondweishu, weishu[startindex]); //check找到的数是否<end for (j = cmpindex-1; j >= 0;j--) { if (fibnum[startindex][j] < second[j] ) { return startindex; } } //判断是否==end sameindex = 0; for (j = cmpindex - 1; j >= 0; j--) { if (fibnum[startindex][j] == second[j]) { sameindex +=1; } } if (cmpindex == sameindex) //==end { return startindex; } return 0; } else { startindex += 1; } } } else { //end要找个<=end的 while (1) { findflag = 0; //从startindex开始找起,从最高位开始比较 if (secondweishu > weishu[startindex]) { return startindex; } for (i = num - 1; i >= 0; i--) { if (fibnum[startindex][i] < second[i]) { findflag = 1; //找到大数 break; } else if (fibnum[startindex][i] == second[i]) //数字相同,那要继续比较 { if (i == 0) { findflag = 1; } else { continue; } } else { //比现在的数大,那就只能break break; } } if (1 == findflag) { return startindex; } else { startindex -= 1; } } } } int main() { freopen("input.txt","r",stdin); int index1 = 0; int index2 = 0; int nn = 0; int bb = 0; int i = 0; int l = 0; int k = 0; //一共有105位最大,那就求出在105位范围内的fib数 initfib(); getfib(); while ((scanf("%s %s", a, b) != EOF && (a[0] != '0' || b[0] != '0'))) { //init(); parse(); //分解输入输出 //分析输入的长度,上面parse函数已经得到长度了 //然后从位数开始找起 index1 = find(1); if (0 != index1) { index2 = find(2); } if (0 != index1) { ans = index2 - index1 + 1; } else { ans = 0; } if (0 == ans) { ans = ans; } printf("%d\n",ans); //下面注释的是第2种做法可以AC /*firstweishu = strlengths(a); secondweishu = strlengths(b); x = 0; index1 = findnew(first, firstweishu); nn = x; x = 0; index2 = findnew(second, secondweishu); bb = x; if (nn == 1 && bb == 1) { printf("%d\n", index2 - index1 + 1); continue; } else if (nn == 1 && bb == 0) printf("%d\n", index2 - index1 ); else if (nn == 0 && bb == 1) printf("%d\n", index2 - index1 + 1); else printf("%d\n", index2 - index1);*/ //initmatrix(); } return 0; }