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\n",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\n",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\n",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\n",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%%\n",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\n",b[n]/b[m]/b[n-m] * a[m]);
    }

}
posted @ 2017-02-13 20:11  pengwill  阅读(157)  评论(0编辑  收藏  举报