HDU-1316 How Many Fibs? 大数、二分问题 (C语言)
先就题目意思做简单介绍,题中要求在给定的两个数a,b(a,b<=10^100)之间[a,b]计算有多少个斐波那契(Fibonacci)数,注意这里约定:
f1 := 1
f2 := 2
fn := fn-1 + fn-2 (n >= 3)
基本思路如下:
1.鉴于有多组测试数据且斐波那契数又是一组特殊的数组(每一项与前驱有一定的关系),采用打表的方式,将1-10^100之间所有的斐波那契数储存起来.
2.录入两个字符串作为上下界.
3.在斐波那契数组中检索上下界的位置,直接求出中间存在斐波那契数的个数.
代码如下:
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> #define M 105 char a[M+2],b[M+2]; char book[1000][M+2]; int cmp(char *s1,char *s2) { for(int i=0;i<=M;++i) { if(i==M) { return s1[i]-s2[i];//如果到最后一位相等,要保证返回0; } if(s1[i]==s2[i]) continue; else { return s1[i]-s2[i]; } } } //一下两个函数是二分查找上下界的位置. //查找原则是下界数组坐标减一,上界数组坐标加一 int find1(int i,char *x) { int low=0,high=i,mid; //定义左右指针,中间指针 while(low<=high) { mid=(low+high)/2; int t=cmp(book[mid],x); if(t>0) high=mid-1;//改变左右界,并偏移(为了使左右指针交错) else if(t==0) return mid-1; else low=mid+1; } return high; //跳出时, high 变量在左边 } int find2(int i,char *x) { int low=0,high=i,mid; while(low<=high) { mid=(low+high)/2; int t=cmp(book[mid],x); if(t>0) high=mid-1; else if(t==0) return mid+1; else low=mid+1; } return low; } int main() { int p=M,i=2; //p用于标记最高位的位置 book[0][M]=1,book[1][M]=2; while(book[i-1][M-100]<=1) { for(int j=M;j>=p;--j) book[i][j]=book[i-1][j]+book[i-2][j]; for(int j=M;j>=p;--j) { int c=book[i][j]/10; book[i][j]%=10; book[i][j-1]+=c; } //即时进位操作 if(book[i][p-1]>0) //判断是否最高位发生变化 --p;//如果当前的最高位的下一位不为零,则指针减一 ++i; } while(scanf("%s%s",a,b),a[0]-'0'||b[0]-'0') { int cnt=0,p; int last1=strlen(a)-1; int last2=strlen(b)-1; for(int j=last1,k=M;j>=0;--j,--k) { a[k]=a[j]-'0'; a[j]=0; //消除干扰比较的因素,置零操作 } for(int j=last2,k=M;j>=0;--j,--k) { b[k]=b[j]-'0'; b[j]=0; } int l=find1(i-1,a); int r=find2(i-1,b); printf("%d\n",r-l-1); memset(a,0,sizeof(a)); //清除上一次操作的数据遗留 memset(b,0,sizeof(b)); } return 0; }