我是靠谱客的博主 靓丽音响,最近开发中收集的这篇文章主要介绍牛客练习赛35 - B背单词 - 3维的dp,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

题目描述

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[5005][2][55]的数组

dp[i][j][k]:=判断到第i位,第i位的元素是j(j==0表示元音,j==1表示辅音),重复了k次有几个单词。

eg、dp[1][0][1]=5。第1位是元音有5种;dp[1][1][1]=21。第1位是辅音有21种

dp[2][0][2]=25。第2位是元音,且第1位也是元音有25种。

递推方程:

for(int j=1;j<=min(b,i-1);j++)dp[i][0][1]=(dp[i][0][1]+dp[i-1][1][j]*5)%mod;

第i位是元音,且第i-1位不是元音的情况,也就是说第i-1位是辅音的所有情况之和*5

for(int j=1;j<=min(a,i-1);j++)dp[i][1][1]=(dp[i][1][1]+dp[i-1][0][j]*21)%mod;

第i位是辅音,且第i-1位不是辅音的情况,也就是说第i-1位是元音音的所有情况之和*21

那么我们知道动态规划是由已知到未知的,怎么赋初值呢?

对于每个i,我们可以求出从元音重复个数从2到a的情况,和辅音重复个数为从2到b的情况,然后用递推方程求出在i位置上之重复1次的情况。

for(int j=2;j<=min(a,i);j++){//初始化,到第i个位置时连续2个元音及以上的情况
    dp[i][0][j]=dp[i-1][0][j-1]*5%mod;
}
for(int j=2;j<=min(b,i);j++){//初始化,到第i个位置时连续2个辅音及以上的情况
    dp[i][1][j]=dp[i-1][1][j-1]*21%mod;
}

(dp小白只能这样理解了qwq,每次推的时候都懵的一批,不知道怎么赋初值,不会推qwq)

代码如下:

#include<iostream>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<cmath>
#include<set>
#include<map>
#include<stack>
#include<sstream>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

const int N=5005,mod=1e9+7;
ll dp[N][2][55];
int main(){
    int t,a,b,n;
    scanf("%d",&t);
    while(t--){
        memset(dp,0,sizeof(dp));
        scanf("%d%d%d",&n,&a,&b);
        dp[1][0][1]=5;dp[1][1][1]=21;
        for(int i=2;i<=n;i++){
            for(int j=2;j<=min(a,i);j++){
                dp[i][0][j]=dp[i-1][0][j-1]*5%mod;
            }
            for(int j=2;j<=min(b,i);j++){
                dp[i][1][j]=dp[i-1][1][j-1]*21%mod;
            }
            for(int j=1;j<=min(b,i-1);j++)dp[i][0][1]=(dp[i][0][1]+dp[i-1][1][j]*5)%mod;
            for(int j=1;j<=min(a,i-1);j++)dp[i][1][1]=(dp[i][1][1]+dp[i-1][0][j]*21)%mod;
        }
        ll ans=0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=a;j++){
                ans=(ans+dp[i][0][j])%mod;
            }
            for(int j=1;j<=b;j++){
                ans=(ans+dp[i][1][j])%mod;
            }
        }
        printf("%lldn",ans%mod);
    }
}

 

最后

以上就是靓丽音响为你收集整理的牛客练习赛35 - B背单词 - 3维的dp的全部内容,希望文章能够帮你解决牛客练习赛35 - B背单词 - 3维的dp所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(48)

评论列表共有 0 条评论

立即
投稿
返回
顶部