How Many Fibs? HDU 1316 解题思路

原题

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

题目大意
给出区间 [a, b],输出 [a, b] 内含有的斐波那契数的总个数。

解题思路

数据范围 a<=b<=10^100,即位数不超过100,数组不用开很大,直接打表,还要注意是闭区间
涉及到大整数加法,注意加完后存入数组的字符串为倒序,后面做字符串比较的时候需要倒过来再进行比较。
需要四个 子函数

string &add(string &a, string &b);//大整数加法函数;引用可以减少内存占用,函数引用可以节省时间
void fibonacci();//求斐波那契序列
bool cmp(string &a, string &b);//对两个字符串作比较
long long fibsn(string &d);//求 0 ~ n 内的斐波那契数个数
//两个个全局变量
string f[1000];
map<string, bool> mark;//这个map方便了后面判断该数是否为斐波那契数,因为对闭区间需要做特殊判断

主函数

int main()
{
    string a, b;
    fibonacci();//先把斐波那契序列求出来存入数组当中
    while (cin >> a >> b)
    {
        if (a == "0" && b == "0")//循环跳出条件
            break;
        if (mark.find(a) == mark.end())//在mark中找到是否存在
        {//如果a不是斐波那契数,那么直接减去
        //因为如果a是斐波那契数的话
        //直接用0~b的斐波那契数个数减去0~a内斐波那契数个数会把a减掉,最后结果会少一个
        //所以要特殊判断a是否为斐波那契数
            long long t = fibsn(b) - fibsn(a);
            printf("%lld\n", t);
        }
        else
        {//如果a是斐波那契数,那么需要多加上一个a
            long long t = fibsn(b) - fibsn(a) + 1;
            printf("%lld\n", t);
        }
    }
}

子函数代码

string &add(string &a, string &b)
{
    int t = 0;
    string &c = *(new string());
    for (int i = 0; i < a.size() || i < b.size(); i++)
    {
        if (i < a.size())
            t += (a[i] - '0');
        if (i < b.size())
            t += (b[i] - '0');
        c += (t % 10) + '0';
        t /= 10;
    }
    if (t != 0)
        c += t + '0';
    return c;
}

void fibonacci()
{
    f[1] = "1";
    f[2] = "1";
    mark["1"] = true;
    for (int i = 3; i < 1000; i++)
    {
        f[i] = add(f[i - 1], f[i - 2]);
        string tmp;
        for (int j = f[i].size() - 1; j >= 0; j--)
            tmp += f[i][j];
        mark[tmp] = true;
    }
}

bool cmp(string &a, string &b)
{
    string aa;
    //因为存入数组的斐波那契数是导致的,对比两个字符串的时候需要将斐波那契数转过来再进行比较
    for (int i = a.size() - 1; i >= 0; i--)
        aa += a[i];
    if (aa.size() > b.size())
        return aa.size() > b.size();
    else if (aa.size() < b.size())
        return aa.size() > b.size();
    else
    {
        if (aa == b)
            return false;
        return aa > b;
    }
}

long long fibsn(string &d)
{
    long long count = 0;
    for (int i = 2; i < 1000; i++)
    {
        if (cmp(f[i], d))
            break;
        count++;
    }
    return count;
}

有错误欢迎指出。如果你们有更好的方法希望能够向你们学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值