zoukankan      html  css  js  c++  java
  • 递推的一点理解

    引例:

    洛谷P1225

    题目描述

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

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

    输入输出格式

    输入格式:

    一个数字,楼梯数。

    输出格式:

    走的方式几种。

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

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

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

    233333这是什么大水题

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

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

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

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

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    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<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    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啦。

    个人想法,

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

  • 相关阅读:
    verilog之计数器0~9999——数码管显示
    C语言的谜题
    modelsim SE6.2b的常用问题
    [转载]MDK常见报错(编译arm)
    Nios II之LED实验(SDRAM+EPCS4配置)————基于Altera的DE0开发板
    poj2210
    poj1161
    poj1555
    poj2337
    poj1107
  • 原文地址:https://www.cnblogs.com/this-is-M/p/10485446.html
Copyright © 2011-2022 走看看