小明走楼梯——斐波那契数列的变态版变种

小明走楼梯

Description

小明来走楼梯啦! 众所周知小明有个怪癖,就是上楼梯的时候一步跨的台阶数一定是2的幂。
那么问题来了,对于一个有n个台阶的楼梯,小明有多少种不同的上楼梯的办法使得他刚好走完这个楼梯?

Input

第一行是一个正整数T,表示有T组测试数据。 每组测试数据有一行一个正整数n,表示楼梯的台阶数。
(1<=T<=50000,1<=n<=50000)

Output

每组数据输出一行,表示小明的上楼梯的方案的个数。 由于这个答案会很大,只要输出方案数对10000取模的答案即可。

Sample Input

4
1
2
3
4

Sample Output

1
2
3
6

C++代码:

#include<iostream>
#include<cmath>
using namespace std;

int fk[50001] = {0};    #将上楼梯的种类存在全局数组fk[]里,并将其初始化为0

int f(int n)
{
    if (n == 0)        #假设n=0时,fk[0]=1,这样后面当n=2^k时可以直接套用表达式,避免分情况讨论
    {
        fk[0] = 1;
        return fk[0];
    }
    else if (n == 1)   #n=1时当然只有一种方法
    {
        fk[1] = 1;
        return fk[1];
    }
    else
    {
        if (fk[n] != 0)   #当fk[n]不为0,即这一步已经算过时,则直接返回该值
        {
            fk[n] %= 10000;
            return fk[n];
        }
        int item = int(log(n) / log(2)) + 1;   #这里利用换底公式,计算出递归表达式应该由item个项组成
        for (int k = 0; k < item; k++)
        {
            fk[n] += f(n - (1 << k));    #递归表达式
        }
        fk[n] %= 10000;    #将最后结果取模
        return fk[n];
    }
}

int main()
{
    int group;
    cin >> group;
    while (group > 0)
    {
        int n;
        cin >> n;
        cout << f(n) << endl;
        group--;
    }
    system("pause");
    return 0;
}

这道题的思路,跟一道很经典的也是小明爬楼梯的题很类似Climbing Stairs(话说小明真是人才,爬楼梯都有这么多种爬法~~)
这道题的思路,首先要列出递归表达式。
首先我们假设我们的小明同学已经走了好几步了,就差最后一步就能爬到n层台阶结束游戏。这样我们计算一下有几种这样的情况(差一步就能爬到n层)。因为一步只能跨2的幂次方阶台阶,所以这最后一步可以跨1,2,4,8,……,2^k,因为每一步都不能大于n,所以取k=log(n)。
因此我们有:f(n) = f(n-2^0) + f(n-2^1) + f(n-2^2) + …… + f(n-2^k)。
所以结果显而易见,剩下的就是想办法提高算法的效率。我这里没有多想,就简单的用一个数组保存起前面的数据,以达到空间换时间的想法。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值