美文网首页
递推总结

递推总结

作者: 清秋雨月 | 来源:发表于2020-01-22 22:19 被阅读0次

    递推总结

    来自重庆宏帆八中初2022级1班的一名学生

    被某郭茂老师被迫强行自愿写总结!!!


    什么是递推

    f(n) = 2f(n - 1) + 2
    • 递推算法是一种简单的算法,即通过已知条件,利用特定关系得出中间推论,直至得到结果的算法.递推算法分为顺推逆推两种.

    • 递推不同于递归,相对于递归算法,递推算法免除了数据进出栈的过程,也就是说,不需要函数不断的向边界值靠拢,而直接从边界出发,直到求出函数值.

    简单的顺推

    所谓顺推法是从已知条件出发,逐步推算出要解决的问题的方法叫顺推.

    简单的逆推

    所谓逆推法从已知问题的结果出发,用迭代表达式逐步推算出问题的开始的条件,即顺推法的逆过程,称为逆推.


    五种典型的递推关系

    Fibonacci数列

    在所有的递推关系中,Fibonacci数列是最常见的.

    看着代码,好像没啥问题,但你要仔细一想就会发现问题,第i月的卵的数量不是这样的,因为有些之前的卵已经长成虫,而我们再次算上了这些变成虫的卵,所以就多算了,而上面的代码就犯了这个错误,正确代码应该减去已经长成虫的卵.

    代码如下

      #include <cstdio>
      int main() {
        long long f[55],g[55]; // f[i]表示第i月成虫数量,g[i]表示第i月新产下的卵
        g[0] = 0;
        f[0] = 0; 
        int x,y,z;
        scanf("%d %d %d",&x,&y,&z);
        for (int i = 1;i <= x; i++) {
            f[i] = 1;
            g[i] = 0; //初始化 
        }    
        g[x + 1] = y;
        f[x + 1] = 1;
        for (int i = x + 2; i <= z + 1; i ++) {
            //f[i] = f[i - x - 1] + f[i - x - 2] * y + g[i - x - 2];
            f[i] = f[i - 1] + g[i - 2];
            g[i] = g[i - x] + (f[i - x] - f[i - x - 1]) * y;
        }
        printf("%lld",f[z + 1]);
            return 0;
      }
    

    Hanoi塔问题

    分析

    设h(n)为第n个盘子从a柱移到c柱所需移动的盘次.显然,当n = 1时,只需把a柱上的盘子直接移动到c柱就可以,故h(1) = 1.当n = 2时,先将a柱上面的小盘子移动到b柱上面去;然后将大盘子从a柱移到c柱:最后,将b柱上的小盘子移到c柱上,共三个盘次,故h(2) = 3.以此类推,当a柱上有n个盘子,总是先借助c柱把上面的n - 1个盘子移动到b柱,然后再把a柱最下面的盘子移动到c柱上;再借助a柱把b柱上的n - 1个盘子移动到c柱上;总共移动h(n - 1) + 1 + h(n - 1)个盘次.所以可得到h(n) = 2h(n - 1) + 1,边界条件:h(1) = 1.

    代码如下

      #include <cstdio>
      long long h[65];
      int main() {
        int n;
        scanf("%d",&n);
        h[1] = 1;
        for (int i = 2;i <= n; i++) {
            h[i] = 2 * h[i - 1] + 1;
        }
        printf("%lld",h[n]);
        return 0;
       }
    

    当然你也可以用递归的方法做,通过推理可以推出h(n) = 2 ^ n - 1.

    代码如下

      #include <cstdio>
      #include <cmath>
      int main() {
         long long n;
         scanf("%lld",&n);
         long long sum;
         sum = pow(2 , n) - 1;
         printf("%lld",sum);
         return 0; 
      }
    

    平面分割问题

    分析

    当平面上已有n - 1条曲线将平面分割成a(n - 1)个区域后,第n条曲线每与曲线相交一次,就会增加一个区域,因为平面上已经有了n - 1条封闭曲线,且第n条曲线与已有的每一条封闭曲线恰好交于两点,且不会与任两条曲线交于同一点,故平面上增加 2(n - 1) 个区域,加上已有的 a(n - 1) 个区域,一共有a(n - 1) + 2(n - 1) 个区域.所以本题的递推关系是 a(n) = a(n - 1) + 2 (n - 1),边界条件是a(1) = 1.

    代码如下

      #include <cstdio>
      int a[46346];
      int main() {
        int n;
        a[1] = 2;
        scanf("%d",&n);
        for (int i = 2;i <= n; i++) {
            a[i] = a[i - 1] + 2 * (i - 1);
        }
        printf("%d",a[n]);
        return 0;
      }
    

    当然你还是可以用递归的方法来做.可以推出公式 a(n) = n * (n - 1) + 2.

    代码如下

      #include <cstdio>
      int main() {
        int n;
        scanf("%d",&n);
        printf("%d",n * n - n + 2);
        return 0;
      }
    

    Catalan数

    分析

    令一个k值,k从2开始到n - 1结束,剩下的是 n - k + 1 边形,令f(n)为n边形的划分方式,那么 f(n) = f(k) * f(n - k + 1) (k从2开始,到n - 1结束)想一下为什么要用乘法

    代码如下

      #include <cstdio>
      long long sum;
      long long f[42];
      int main() {
        int n;
        scanf("%d",&n);
        f[1] = 1;
        f[2] = 1;
        if (n == 1 || n == 2) {
            printf("0");
            return 0;
        }
        for (int i = 1;i <= n; i++) {
            for (int k = 2 ; k <= i - 1; k++) {
                f[i] += f[k] * f[i - k + 1];
            }
        }
        printf("%lld",f[n]);
        return 0;
      }
    

    第二类stirling数

    分析

    记f(n, m)为n个球,m个盒子的方法总数.从中取出一个球k有以下情况.当k独占一个盒子,方案数为f(n - 1,m- 1);当k与其他球共享一个盒子,方案数:m * f(n-1,m).那么一共有 f(n - 1,m - 1) + m * f(n - 1,m) 种方法.即 f(n) = f(n - 1,m - 1) + m * f(n - 1,m) 种方法.

    代码如下

      #include <cstdio>
      long long a[25][25];
      int main() {
        int n, m;
        scanf("%d %d", &n, &m);
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= i; j++) {
                if (i == j) {
                    a[i][j] = 1;
                } else {
                    a[i][j] = a[i - 1][j - 1] + j * a[i - 1][j];
                }
            }
        }
        printf("%lld", a[n][m]);
        return 0;
      }
    

    感谢观看这个不正经总结

    相关文章

      网友评论

          本文标题:递推总结

          本文链接:https://www.haomeiwen.com/subject/wjcpzctx.html