BigNums——HDUOJ 1316

来源:互联网 发布:淘宝手办现货可信? 编辑:程序博客网 时间:2024/06/05 05:04

原题

  • 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 == tail)//二分结束        {                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);        }    }}
原创粉丝点击