2023百度之星第三场第一题

比赛的时候想半天没有想出来,赛后补题发现是一道动态规划问题。

定义一个二维dp数组,第二维度维护当前字符串结尾的三种可能,第一种以s结尾,第二种最后以sh为结尾,第三种则是以其他字符结尾。设定最多组成3个shs,不然会发生重复。

if(j==9)代表刚好组成3个shs,下一个状态可以为当前字符串加上26个字符中随便一个,即加上26ll*dp[i][j]。

if(j%3==1) 表示以s结尾,以s结尾的情况下加上s还是j不变,i+1;以s结尾的情况下加上h变为第二种情况即以sh结尾,j+1,i+1;以s结尾的情况下加上其他字符变为第三种情况,即以其他字符结尾,j/3*3,i+1。

else 表示以sh或者以其他字符结尾的情况,此时shs的数量未达到3个。若是以sh结尾,则加上s后j+1刚好跳到下一个状态,或者加上一个其他字符,j变为j*3/3;若是以其他字符结尾,则加上s后跳转到j+1,或者加上一个其他字符,j变成j*3/3;因此这两种情况都是一样的,可以放在一起讨论。

最后输出dp[n][9](代表刚好组成三个shs的情况)

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
int dp[1000010][10];//第二维度只包含s,sh,shs三种情况 
int main(){
	int n;
	scanf("%d",&n);
	dp[0][0]=1;//定义初始状态 
	for(int i=0;i<n;i++){
		for(int j=0;j<10;j++){
			if(j==9){//刚好组成3个shs 
				dp[i+1][j]=(dp[i+1][j]+26ll*dp[i][j])%mod;//下一个状态由当前状态乘26所得 
			}
			else if(j%3==1){//以s结尾 
				dp[i+1][j]=(dp[i+1][j]+dp[i][j])%mod;//s后加的字符仍为s ,第二维度仍为j 
				dp[i+1][j+1]=(dp[i+1][j+1]+dp[i][j])%mod;//s后加的字符为h,变为第二种情况以sh结尾,第二维度变为j+1 
				dp[i+1][j/3*3]=(dp[i+1][j/3*3]+24ll*dp[i][j])%mod;//s后加的字符为除s和h外的任意24个字符,重新变为整shs的情况 
			}
			else {//以sh和以其他字符结尾的一起讨论 此时j可能为0可能为2 
				dp[i+1][j+1]=(dp[i+1][j+1]+dp[i][j])%mod;//以sh为结尾的情况下可以选择以s为结尾,下一个状态就直接加上dp[i][j] 或者 以其他字符为结尾的情况下选择以s为结尾 
				dp[i+1][j/3*3]=(dp[i+1][j/3*3]+25ll*dp[i][j])%mod; //以sh为结尾的情况下加上了除s外的其他字符,重新变为整shs的情况 或者 以其他字符为结尾的情况下再选择以其他字符结尾 
			}
		}
	}
	printf("%d\n",dp[n][9]);//最后输出的是刚好有3个shs的情况,所以第二维度为9 
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值