hdu_1627_下沙的沙子有几粒?

题目链接
hdu_1627_下沙的沙子有几粒

Problem Description:
       2005年11月份,我们学校参加了ACM/ICPC 亚洲赛区成都站的比赛,在这里,我们获得了历史性的突破,尽管只是一枚铜牌,但获奖那一刻的激动,也许将永远铭刻在我们几个人的心头。借此机会,特向去年为参加ACM亚洲赛而艰苦集训了近半年的各位老队员表示感谢。
       实际上,除了获奖以外,在这次比赛期间还有一件事也让我们记忆深刻。那是比赛当天等待入场的时候,听到某个学校的一个队员在说:“有个学校的英文名很有意思,叫什么Hangzhou Dianzi University”. 哈哈,看来我们学校的英文名起的非常好,非常吸引人呀。
       不过,事情的发展谁也没有料到,随着杭电英文校名的这一次曝光,影响越来越大,很多人开始对杭电英文校名进行研究,不久以后甚至还成立了一个专门的研究机构,叫做“HDU 校名研究会”。并不断有报道说-相-当-多的知名科学家改行,专门对该问题进行研究,学术界称之为“杭电现象”。很多人在国际知名期刊上发表了研究论文,这其中,尤以中国超级女科学家宇春小姐写的一篇研究报告最为著名,报告发表在science上,标题是“杭电为什么这样红?” 文中研究发现:Hangzhou Dianzi University这个校名具有深刻的哲学思想和内涵,她同时提出了一个大胆的猜想:“假定一个字符串由m个H和n个D组成,从左到右扫描该串,如果字符H的累计数总是不小于字符D的累计数,那么,满足条件的字符串总数就恰好和下沙的沙粒一样多。”
这就是当今著名的“宇春猜想”!
       虽然还没能从数学上证明这个猜想的正确性,但据说美国方面在小布什的亲自干预下,已经用超级计算机验证了在(1<=n<=m<=1000000000000)时都是正确的。my god! 这是一个多么伟大的猜想!虽然我们以前总说,21世纪是属于中国的,可还是没想这一天来的这么早,自豪ing… + 感动ing…
感动和自豪之余,问题也来了,如果已知m和n的值,请计算下沙的沙粒到底有多少。
Ps:
1. 中国有关方面正在积极行动,着手为宇春小姐申报诺贝尔奖。
2、“宇春猜想”中提到的H和D组成的字符串现在被学术界成为“杭电串串”(“杭电串串”前不久被一个卖羊肉串的注册了商标,现在我校正在积极联系买断,据说卖方的底价是1000万欧元,绝不打折,看来希望不大,sigh…)

Input
输入数据包含多个测试实例,每个占一行,由两个整数m和n组成,m和 n 分别表示字符串中H和D的个数。由于我们目前所使用的微机和老美的超级计算机没法比,所以题目给定的数据范围是(1<=n<=m<=20)。

Output
对于每个测试实例,请输出下沙的沙粒到底有多少,计算规则请参考“宇春猜想”,每个实例的输出占一行。

Sample Input
1 1
3 1

Sample Output
1
3

分析:
       我做这道题,开始是用递归做的,类似 dfs 枚举了每个状态先放 H 还是先放 D ,在测试数字在15以内的时候就可以很快得出答案,但再大就 T 了,想想也是在情理之中,他的状态数是成指数上升的。因此我就用递归对 10 以内的数据打了个表,发现了一个递推关系,
a[m][n] = a[m-1][n] + a[m][n-1],所以我是在完全不理解这个关系的情况下AC的 =_=! ….
现在来分析下这个式子,对于一组 m,n,a[m][n] 表示m个 H ,n个 D 满足条件的放法,那么怎样从前一种状态转移过来呢,因为对于每种情况我们可以确定最后一个位置放得不是 H 就是 D ,所以就可以抓住这一点来转移了:
对于 一组m,n:
1.固定最后一个位置放 H ,那么前面的放法就是 a[m-1][n] 了,应该很容易理解。
2.固定最后一个位置放 D ,则前面放法就是 a[m][n-1] 了。
由于只有这两种互不重叠的情况,所以就有了以上的递推公式了,最后有没有发现和高中组合数里的一个公式很像,C(m,n)=C(m-1,n-1)+C(m-1,n) ,貌似可以借助这个公式理解一下。

下面就见代码君咯~

#include <iostream>
#include <cstdio>
using namespace std;
long long a[21][21];
int main(){
    for(int i=1;i<=20;i++){
        for(int j=1;j<=i;j++){//j大于i时为0种
            if(j==1)a[i][j]=i;//j=1时为i种
            else a[i][j]=a[i-1][j]+a[i][j-1];
        }
    }
    int m,n;
    while(cin>>m>>n){
        cout<<a[m][n]<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值