SOJ 1029

1029. Rabbit

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

Description

The rabbits have powerful reproduction ability. One pair of adult rabbits can give birth to one pair of kid rabbits every month. And after m months, the kid rabbits can become adult rabbits.

    As we all know, when m=2, the sequence of the number of pairs of rabbits in each month is called Fibonacci sequence. But when m<>2, the problem seems not so simple. You job is to calculate after d months, how many pairs of the rabbits are there if there is exactly one pair of adult rabbits initially. You may assume that none of the rabbits dies in this period.

Input

The input may have multiple test cases. In each test case, there is one line having two integers m(1<=m<=10), d(1<=d<=100), m is the number of months after which kid rabbits can become adult rabbits, and d is the number of months after which you should calculate the number of pairs of rabbits. The input will be terminated by m=d=0.

Output

You must print the number of pairs of rabbits after d months, one integer per line.

Sample Input

2 33 51 1000 0

Sample Output

591267650600228229401496703205376

Problem Source

ZSUACM Team Member


  正如题意所说,题目类似于斐波那契数列,当m=2时即为斐波那契数列,a[i]=a[i-1]+a[i-2]。当m为更为一般的情况时即为a[i]=a[i-1]+a[i-m],a[1]至a[m]的值自然是为1到m。依此递推求出a[d+1]即可。但要注意题目给出的数据是大数,只能用int数组来保存,所以做加法时用数组对应位数依次运算即可。

  尤其要注意m=1时,a[i]=2*a[i-1],做加法时不要出现进位错误。


// Problem#: 1029
// Submission#: 5052934
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include<iostream>
#include<cstring>
using namespace std;
int bigINT[110][41];//保存大数的数组,第i个数的各个数字就保存在bigINT[i]中 
int m,d,flag;//注意flag的作用是为了判断当m=1时是否需要进位 
int main()
{
    int index;
    while(cin>>m>>d&&m&&d)
    {
        memset(bigINT,0,sizeof(bigINT));
        for(int i=1;i<=m;++i)
        {
            if(i<10) bigINT[i][40]=i;//注意m的范围是[1,10],而10是两位数所以需要单独操作,并确保个位数在每行的最后一个位置 
            else 
            {
                bigINT[i][40]=0;
                bigINT[i][39]=1;
            }
        }
        if((d+1)<=m) //此时第1至第m个数已经求出,若(d+1)不大于m则可直接输出 
        {
            for(int i=0;i<41;++i)
            {
                if(bigINT[d+1][i])//从第一个不为0的数字开始输出 
                {
                    index=i;
                    break;
                }
            }
            for(;index<41;++index) cout<<bigINT[d+1][index];
            cout<<endl;
        }
        else//若d+1大于m则求出第d+1个数的值 
        {
            for(int i=m+1;i<=(d+1);++i)
            {
                for(int j=40;j>=0;--j)
                {
                    if(m!=1)//当m不为1时,a[i-1]和a[i-m]不是同一个数,所以如果有进位的话在只需要在a[i-m]的对应位数的数字上加一即可 
                    {
                        bigINT[i][j]=(bigINT[i-m][j]+bigINT[i-1][j])%10;
                        if(bigINT[i-m][j]+bigINT[i-1][j]>9)
                        {
                            bigINT[i-m][j-1]++;//这里选择在a[i-m]是因为这次加一会改变数值,而a[i-m]之后不再会用到,所以改变也无妨 
                        }
                    }
                    else//当m=1时,由于a[i-m]和a[i-1]是同一个数,所以在a[i-m]的某个位数上加一则相当于一共加了2,会造成计算错误 
                    {
                        if(flag) //所以这里用flag这一变量来判断是否要向前进1,如果有进位的话不改变a[i-1]的值,而是在外部加1 
                        {
                            bigINT[i][j]=(bigINT[i-m][j]+bigINT[i-1][j]+1)%10;
                            if((bigINT[i-m][j]+bigINT[i-1][j]+1)>9) flag=1;
                            else flag=0;
                        
                        }
                        else 
                        {
                            bigINT[i][j]=(bigINT[i-m][j]+bigINT[i-1][j])%10;
                            if(bigINT[i-m][j]+bigINT[i-1][j]>9) flag=1;
                            else flag=0;
                        
                        }
                    }
                }
            }
            for(int i=0;i<41;++i)//同样从第一个不为0的数字开始输出 
            {
                if(bigINT[d+1][i]) 
                {
                    index=i;
                    break;
                }
            }
            for(;index<41;++index) cout<<bigINT[d+1][index];
            cout<<endl;
        }
    }
    return 0;
}                                 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值