您的位置:首页 > 其它

BigNums——HDUOJ 1316 - How Many Fibs?(斐波那契个数 + 二分法 + 预处理)

2017-10-21 17:54 323 查看

原题

Problem Description

Recall the definition of the Fibonacci numbers:

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 <= 10^100. 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

这题有点坑:

1. F1 = 1,F2 = 2

2. 考虑输入的第一个数有可能为0

3. 考虑输入相同的数(如:1 1或者4 4)

解题思路:

1. 使用string比直接char[]节省内存占用,有c++库函数,用起来方便

2. 预处理:通过string数组先将前500个斐波那契数字算好,存起来

3. 二分法:最后head指针和tail指针相差 1 时,可以直接返回mid值(即head的值【head = mid】)注意:二分法后获得的值sum[mid] <= TestNum(原来要寻找的值)

代码:

#include<stdio.h>
#include <string>
#include <iostream>
using namespace std;
const int MAXFIB = 501;//斐波那契个数
string sum[MAXFIB];
void Add(int num)
{
int i;
int LengthOfTow = sum[num - 1].length() - sum[num - 2].length();//两个数相差的长度
int temp;
short CarryBit = 0;//进位
for (i = sum[num - 2].length() - 1; i >= 0; i--)//从两个数中小的数[F(n-2)]开始,再从**string**数组元素倒退,逐个加法进位
{
temp = (sum[num - 2][i] - '0') + (sum[num - 1][i + LengthOfTow] - '0') + CarryBit;
CarryBit = temp / 10;
sum[num] = char((temp % 10) + '0') + sum[num];
}
for(i = i + LengthOfTow; i >= 0; i--)//从两个数中大的数[F(n-1)]开始进位
{
temp = (sum[num - 1][i] - '0') + CarryBit;
CarryBit = temp / 10;
sum[num] = char((temp % 10) + '0') + sum[num];
}
if (CarryBit != 0)//两数相加,总数位数最多是大数位数+1
{
sum[num] = char(CarryBit + '0') + sum[num];
}
}
void PreFibonacci()//预处理
{
sum[0] = "1";
sum[1] = "2";
int i;
for (i = 2; i < MAXFIB; i++)
{
Add(i);
//cout <<i << "  "<< sum[i] << endl;
}
}
int CompareSiza(string a, string b)//两个string 比较大小//a大返回true,b大返回false
{
if (a.length() != b.length())
{
return a.length() > b.length() ? 1 : -1;//通过长度判断
}
else//从首位开始判断
{
int length = a.length() - 1;
int i = 0;
for (; i <= length; i++) {
if ((a[i] - '0') == (b[i] - '0'))//该位数字相等
{
continue;
}
else
{
return  (a[i] - '0') > (b[i] - '0') ? 1 : -1;
}
}
return 0;//两数相等
}

}
int BinarySearch(string TestNum)//二分查找
{
int head = 0;
int tail = MAXFIB;
int mid = (head + tail) / 2;
int CompareResult;
while (mid != 0||mid != MAXFIB)
{
CompareResult = CompareSiza(sum[mid], TestNum);
if (1 == CompareResult)//mid > testnum
{
tail = mid;
}else if (-1 == CompareResult)
{
head = mid;
}else
{
return mid;//两数相等(找到)
}
mid = (head + tail) / 2;
if (head + 1 == t
4000
ail)//二分结束
{
return mid;
}
}
}

int main()
{
PreFibonacci();//预处理
string a, b;
int aPosition;
int bPosition;
while (cin >> a && cin >> b && ((a[0] - '0') + (b[0] != '0'))!= 0)
{
if (a[0] == '0')//第一个数为0
{
aPosition = -1;
}
else {
aPosition = BinarySearch(a);
if (CompareSiza(sum[aPosition],a) == 0)//判断第一个数是否在斐波那契数列中,是的话需要退一格
{
aPosition--;
}
}

bPosition = BinarySearch(b);

if (bPosition == aPosition)//两数相等
{
if (CompareSiza(sum[aPosition], a) == 0)//属于斐波那契数列
{
printf("1\n");
}else
{
printf("0\n");
}
}else//两数不相等
{
printf("%d\n", bPosition - aPosition);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息