递推的一点理解

引例:

洛谷P1225

题目描述

楼梯有N阶,上楼可以一步上一阶,也可以一步上二阶。

编一个程序,计算共有多少种不同的走法。

输入输出格式

输入格式:

 

一个数字,楼梯数。

 

输出格式:

 

走的方式几种。

看到这个题,首先想到的是用递归,那么我们对于上最后一节台阶的方法数进行一下书写的话,会发现

可以迈一步上去,也可以迈两步上去,那么就有了f(n)=f(n-1)+f(n-2);

这个其实还是比较好想的,仔细研究后发现,这一递推式刚好能够满足所有子问题,然后对一阶台阶和两阶台阶进行一下计算,这个题就OK了。

233333这是什么大水题

but。。。。。。。。。。。

 

 

 

很恶心的事情出现了,由于答案太大,而该死的luogu又不让对大质数取模。。。。

即使是用long long也只能拿一半得分的情况下,只有高精能行了,代码实现如下

思路大概是用数组f[k][j]来存储走k个阶梯所用的步数 最后循环输出

#include
#include
#include
#include
#include
using namespace std;
int n,len=1,f[5003][5003];
void lt(int k)//高精度加法,k来存阶数
{    
    int i;//其实写递归和递推,主要用的是循环操作,可以函数内嵌来循环,好处是好想而且代码简介,但是不好的地方是对于一些取模等操作,有些麻烦,
所以我们使用循环的方法来解决
for(i=1;i<=len;i++) f[k][i]=f[k-1][i]+f[k-2][i]; for(i=1;i<=len;i++) if(f[k][i]>=10)//进位 { f[k][i+1]+=f[k][i]/10; f[k][i]=f[k][i]%10; if(f[k][len+1])len++; } } int main() { int i; cin>>n; f[1][1]=1; f[2][1]=2; //特判一下1,2 for(i=3;i<=n;i++) //从3开始的话,避免越界 lt(i); for(i=len;i>=1;i--) cout<<f[n][i];//最后逆序输出 return 0; }

好了,这个题解决完了,那么我们看一下它的升级版。。。。。。。虽然都是橙题。。。。。。

P1192 台阶问题

题目描述

NN级的台阶,你一开始在底部,每次可以向上迈最多KK级台阶(最少11级),问到达第NN级台阶有多少种不同方式。

输入输出格式

输入格式:

 

两个正整数N,K。

 

输出格式:

 

一个正整数,为不同方式数,由于答案可能很大,你需要输出ans mod100003后的结果。

这。。。。。。人类福音啊喂

这个题的话,可以照搬上一题的思想,但是这里的最多迈两阶变成了最多迈k阶

这样的话,我们就可以用一套循环来解决,这个是中心部分

for(int i=1;i<=n;++i)
    {
        for(int j=1;j<=k&&i-j>=0;++j)
        qaq[i]+=qaq[i-j];
        
        
        qaq[i]%=100003;
    }

很容易看到,由外循环i控制第几节台阶的方案数,内循环j控制迈几步

内循环完事之后取模一次,然后重复。。。。。

AC代码如下

#include
#include
#include
#include
#include
using namespace std;    
int n,k,qaq[100001]={1}; 
int main()
{
    cin>>n>>k;
    for(int i=1;i<=n;++i)
    {
        for(int j=1;j<=k&&i-j>=0;++j)
        qaq[i]+=qaq[i-j];
        
        
        qaq[i]%=100003;
    }
    cout<<qaq[n];
    return 0;
}

这个题还有一点,是判断一下当前的台阶总数是不是比最多迈的台阶数大,也就是i-j>=0;

这里进行一下特判就OK啦。

个人想法,

递归和递推都是把复杂问题简单化,通过若干个子问题来解决父问题(让儿子干死他爹), 解这类题的关键就是找到一个公式能够持续循环下去,其实我觉得在学习了数学归纳法和数论的相关内容之后,对于递归和递推的理解会更好一点。

转载于:https://www.cnblogs.com/this-is-M/p/10485446.html

你可能感兴趣的:(递推的一点理解)