H - 无聊的小明 HRBUST - 2181 [数位DP] 学习中ing

无聊的小明
Time Limit: 3000 MSMemory Limit: 32768 K
Total Submit: 108(61 users)Total Accepted: 52(46 users)Rating: Special Judge: No
Description

小明想用两个字母a和b创造一个长度为n的单词,但是他又不希望连续的a超过p个,同时也不希望连续的b超过q个。那么小明有能创造出多少个不用的单词呢?

Input

每组数据包括一行,三个整数n,p,q分别对应题意。

其中max(a, b) <= n <= 50000,1 <= a, b <= 300。

Output

输出不同的单词的个数。个数要对1000000007取模。

Sample Input

3 2 1

Sample Output

4

Source
2014.11.29新生赛-热身赛

思路:

1.定义DP[n][0] : 长度为n的,当前字母为0的方案数

那么有 dp[n][0]=sigma dp[i-j][1]   j∈[n-p,i-1];

dp[n][1]=sigma dp[i-j][0]   j∈[n-p,i-1];


AC代码:

#include <stdio.h>
#include <string.h>
typedef long long ll;

const int MAX_N=1e3+3;
const int MOD=1e9+7;
ll dp[50005][3];

int main(void){
    int n,p,q;
    while(~(scanf("%d%d%d",&n,&p,&q))){
        memset(dp,0,sizeof(dp));
        dp[0][0]=dp[0][1]=1;
        for(int i=1;i<=n;++i){
//            int t=max(0,i-p);
//            for(int j=t;j<=i-1;j++) dp[i][0]=(dp[i][0]%MOD+dp[j][1]%MOD)%MOD;
//            t=max(0,i-q);
//            for(int j=t;j<=i-1;j++) dp[i][1]=(dp[i][1]%MOD+dp[j][0]%MOD)%MOD;
            for(int j=1;j<=p&&j<=i;++j) dp[i][0]+=dp[i-j][1],dp[i][0]%=MOD;
            for(int j=1;j<=q&&j<=i;++j) dp[i][1]+=dp[i-j][0],dp[i][1]%=MOD;
        }
    //    for(int i=0;i<=10;i++)  printf("%d %d\n",dp[i][0],dp[i][1]);
        printf("%lld\n",(dp[n][0]+dp[n][1])%MOD);
    }
}
Nero :   DP题,对于出题人的意思要去揣测,对于长度为0的串是否认为是单词,即是否承认dp[0][0or1]是否可以转移。拿数据去揣摩一下吧。 也可以先承认,因为承认的时候初始化比较方便,如果输出不对,去掉dp[0][0] 和 dp[0][1]   。 就可以了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值