背单词(dp)

版权声明:本文为博主原创文章,转载请说明出处。 https://blog.csdn.net/xianpingping/article/details/85412814

链接:https://ac.nowcoder.com/acm/contest/326/B
来源:牛客网
 

题目描述

winterzz1准备考4级了,现在winterzz1决定把世界上所有单词都背一遍,winterzz1发现任意一个单词最多有A个连续的元音,最多有B个连续的辅音。且单词最长长度为N,winterzz1问你在满打满算的情况他需要背多少单词???

输入描述:

首先输入一个T(T<=100),表示有T组案例,每组案例依次输入三个正整数N,A,B,N<=5000,A<=50,B<=50;

输出描述:

输出winterzz1最多需要背多少单词,结果mod(10^9+7)

示例1

输入

复制

2
2 2 2
500 20 30

输出

复制

702
175540856

备注:

元音字母为a,e,i,o,u,其余21个字母均为辅音

思路:

看到数据量,就想到了dp;然后就想状态,之前做过类似的,就是用三维:i,j,k分别表示当前是哪一位,j代表元音(0)和辅音(1),k代表,到i位为止,j个单词的连续的个数。

这样dp方程就可以推出来了:

dp[i][0][1]=sum(dp【i-1】【1】【1】~dp【i-1】【1】【B】)*5

dp[i][1][1]=sum(dp【i-1】【0】【1】~dp[i-1][0][A])*21

dp【i】【0】【2】=dp【i-1】【0】【1】*5;

dp[i][0][3]=dp[i-1][0][2]*5  等等

同理,辅音也是:

dp【i】【1】【2】=dp【i-1】【1】【1】*21;

dp[i][1][3]=dp[i-1][1][2]*21   等等。

注意:初始化memset超时。改成循环。

代码:

#include<bits/stdc++.h>
using namespace std;
const int mod=1000000000+7;
typedef long long LL;
LL dp[5100][60][60];
int main()
{
    int t,N,A,B;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d%d",&N,&A,&B);
       /// memset(dp,0,sizeof(dp));
        for(int i=0;i<=N;i++)
            for(int j=0;j<=52;j++)
                dp[i][0][j]=dp[i][1][j]=0;///j是当前字母连续的个数
        dp[1][0][1]=5;///0元音
        dp[1][1][1]=21;///1辅音

        for(int k=2;k<=A;k++){
            dp[1][0][k]=0;
        }
        for(int k=2;k<=B;k++){
            dp[1][1][k]=0;
        }
        for(int i=2;i<=N;i++)
        {
            for(int j=1;j<=B;j++){
                dp[i][0][1]+=dp[i-1][1][j]*5%mod;
                dp[i][0][1]=dp[i][0][1]%mod;
            }
            for(int j=1;j<=A;j++){
                dp[i][1][1]+=dp[i-1][0][j]*21%mod;
                dp[i][1][1]=dp[i][1][1]%mod;
            }
            for(int j=2;j<=A;j++){
                dp[i][0][j]=dp[i-1][0][j-1]*5%mod;
                dp[i][0][j]%=mod;
            }
            for(int j=2;j<=B;j++){
                dp[i][1][j]=dp[i-1][1][j-1]*21%mod;
                dp[i][1][j]%=mod;
            }
        }
        LL ans=0;
        for(int i=1;i<=N;i++){
            for(int k=1;k<=A;k++){
                ans=(ans+dp[i][0][k])%mod;
            }
        }
        for(int i=1;i<=N;i++){
            for(int k=1;k<=B;k++){
                ans=(ans+dp[i][1][k])%mod;
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xianpingping/article/details/85412814