zoukankan      html  css  js  c++  java
  • HDOJ(HDU).2044-2049 递推专题

    HDOJ(HDU).2044-2049 递推专题

    点我挑战题目

    HDU.2044

    题意分析

    先考虑递推关系:从1到第n个格子的时候由多少种走法?

    这里写图片描述

    这里写图片描述
    如图,当n为下方格子的时候,由于只能向右走,所以有2中走法。当n为上方格子的时候,由于只能向右走,所以也有2种走法。
    不妨用a[n]来表示第n个格子有几种走法,根据上述描述,不难找出递推关系,a[n] = a[n-1] + a[n-2]。但是对于n<2的数字,就不适用了。也很简单,n<2的时候数一下即可,从1走到1,只有一种走法,从1走到2,有一种走法。问题就解决了。
    然后我们接着考虑从b走到c有几种走法。不放就看样例给的3-6。从图中可以看出,从3-6走的方法和从1-4走的方法总数是一样的。故从b到c的的方法数为a[c-b+1].

    代码总览

    /*
        Title:HDOJ.2044
        Author:pengwill
        Date:2017-2-13
    */
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define ll long long
    using namespace std;
    ll a[51];
    int main()
    {
        a[1] = a[2] = 1;
        for(int i = 3 ; i<=50 ;++i) a[i] = a[i-1] + a[i-2];
        int b,c,t;
        scanf("%d",&t);
        while(t--){
            scanf("%d%d",&b,&c);
            printf("%lld
    ",a[c-b+1]);
        }
        return 0;
    }
    

    HDU.2045

    题意分析

    由于前一个颜色的选择会影响到下一个颜色的选择,对于前n个格子的涂法,就要对前n-1个格子的颜色进行分析。由于要求是首位的颜色不同,那么就要对第n-1个格子是否与第一个格子颜色相同分类讨论。a[n]代表前n个格子的涂法。
    若第一个格子与第n-1个格子的颜色不同,那么第n个格子的就有1种涂法;若第n-1个格子与第一个格子颜色相同,那么第n个格子就有2种涂法,需要注意的是,其实这种情况的方案数是与a[n-2]有关的,因为此时方案数是a[n-2] * 1 * 2 (n-1格子颜色已经确定了)

    代码总览

    /*
        Title:HDOJ.2045
        Author:pengwill
        Date:2017-2-13
    */
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define ll long long
    using namespace std;
    ll a[51];
    int main()
    {
        a[1] = 3; a[2] = 6; a[3] = 6;
        for(int i = 4; i<=50; ++i) a[i] = a[i-2]*2 + a[i-1];
        int n;
        while(scanf("%d",&n) != EOF){
            printf("%lld
    ",a[n]);
        }
        return 0;
    }

    HDU.2046

    题意分析

    详情请见此

    代码总览

    /*
        Title:HDOJ.2046
        Author:pengwill
        Date:2017-2-13
    */
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define ll long long
    using namespace std;
    ll a[51];
    int main()
    {
        a[1] = 1; a[2] = 2;
        for(int i = 3; i<=50; ++i) a[i] = a[i-2] + a[i-1];
        int n;
        while(scanf("%d",&n) != EOF){
            printf("%lld
    ",a[n]);
        }
        return 0;
    }

    HDU.2047

    题意分析

    由于n-1位是否为O,影响第n位的选择,所以很明显,这道题有2种状态,一种是n-1是O,一种是n-1不是O。第n位的方案数就是,n为O的方案 + n不为O的方案。
    a[n]表示O结尾的方案数 b[n]不是以O结尾的方案数,c[n]表示总的方案数。那么c[n] = a[n] + b[n]。
    不难发现:
    a[1] = 1; a[2] = 2; c[1] = 3;
    b[1] = 2; b[2] = 6; c[2] = 8;
    然后分别找一下a[n]和b[n]的递推关系式:
    由于不能有O相连,那么n-1不为O的时候,n位才有可能为O,可以得出:a[n] = b[n-1]
    接着考虑什么时候第n位为非O呢,当第n-1位是O的时候,n可能有EF2种非O选择,当n-1位为O的时候,也有EF2种非O选择,于是有:b[n] = 2 * (a[n-1] + b[n-1])
    有了ab的递推关系式,根据c[n] = a[n] + b[n] 问题也就迎刃而解了。

    代码总览

    /*
        Title:HDOJ.2047
        Author:pengwill
        Date:2017-2-13
    */
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define ll long long
    using namespace std;
    ll a[41],b[41],c[41];
    int main()
    {   // a以O结尾的结果数量 b非以O的数量
        a[1] = 1; a[2] = 2; c[1] = 3;
        b[1] = 2; b[2] = 6; c[2] = 8;
        for(int i = 3; i<=40; ++i){
            a[i] = b[i-1];
            b[i] = 2*(a[i-1] + b[i-1]);
            c[i] = a[i] + b[i];
        }
        int n;
        while(scanf("%d",&n) != EOF){
            printf("%lld
    ",c[n]);
        }
        return 0;
    }
    

    HDU.2048

    题意分析

    此题的递推关系体现在错排公式,详情百度。

    代码总览

    /*
        Title:HDOJ.2048
        Author:pengwill
        Date:2017-2-13
    */
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define ll long long
    using namespace std;
    ll a[21]={0,0,1},b[21] = {0,1};
    ll cal(int i)
    {
        if(b[i] != 0) return b[i];
        else return (cal(i-1)*i);
    }
    void init()
    {
        for(int i = 1;i<=20;++i)
            b[i] = cal(i);
        for(int i = 3; i<=20;++i)
            a[i] = (i-1) * (a[i-1]+a[i-2]);
    }
    int main()
    {
        init();
        int t;
        scanf("%d",&t);
        while(t--){
            int n;
            scanf("%d",&n);
            printf("%.2f%%
    ",100.0*a[n]/b[n]);
        }
    
    }
    

    HDU.2049

    题意分析

    此题的递推关系体现在错排公式,详情百度。

    代码总览

    /*
        Title:HDOJ.2049
        Author:pengwill
        Date:2017-2-13
    */
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define ll long long
    using namespace std;
    ll a[21]={0,0,1},b[21] = {1,1};//a是错排,b是全排列
    ll cal(int i)
    {
        if(b[i] != 0) return b[i];
        else return (cal(i-1)*i);
    }
    void init()
    {
        for(int i = 1;i<=20;++i)
            b[i] = cal(i);
        for(int i = 3; i<=20;++i)
            a[i] = (i-1) * (a[i-1]+a[i-2]);
    }
    int main()
    {
        init();
        int t;
        scanf("%d",&t);
        while(t--){
            int n,m;
            scanf("%d%d",&n,&m);
            printf("%lld
    ",b[n]/b[m]/b[n-m] * a[m]);
        }
    
    }
    
  • 相关阅读:
    搞清楚C#中的值类型(基础类型)和引用类型
    构造动态SQL语句
    Json.net API及常用方法
    泛型代码中的default有何作用
    SQL 中的for xml path()的使用
    fastJosn和JackJson的区别
    箭头函数
    3篇文章初探MVC工作流程
    MVC传递Model之TempData、ViewData、ViewBag区别和用途
    .Net 提交页面,js修改的Label值会丢掉
  • 原文地址:https://www.cnblogs.com/pengwill/p/7367167.html
Copyright © 2011-2022 走看看