[abc279 G] At Most 2 Colors

G - At Most 2 Colors (atcoder.jp)

重点讲解方法三,因为方法三是蒟蒻都能想出来的方法一和方法二都可以借助方法三的思想推出

方法一

这是最简单的设置状态的方法,dp[i]表示前i个的方案数,然后分类

  • [ik+1,i1]有两种颜色

    那么第i位的取值肯定时这两种颜色中的一个,所以就是要×2,考虑如何使得[ik+1,i1]必须有两个颜色,用总方案减去只有一种颜色的方案,也就是dp[i1]dp[ik+1]

dp[i]+=(dp[i1]dp[ik+1])×2

  • [ik+1,i1]只有一种颜色

此时第i位有c种取值,则dp[i]+=dp[ik+1]×c

所以综上:dp[i]=dp[i1]×2+(c2)×dp[ik+1]

方法二

dp[i][1/2]表示[ik+2,i]中有1/2种颜色的方案数

分类讨论,然后枚举j表示[j+1,i]的颜色都相同

dp[i][1]=j=1ik+1(dp[j][1]×(c1)+dp[j][2])dp[i][2]=j=ik+2i1(dp[j][1]×(c1)+dp[j][2])

方法三

dp状态同二

dp[i][1]=dp[i1][1]+dp[ik+1][1]×(c1)+dp[ik+1][2]dp[i][2]=dp[i1][1]×(c1)+dp[i1][2]×2dp[ik+1][1]×(c1)dp[ik+1][2]

  • 对于dp[i][1]

    • ik+1的颜色与[ik+2,i]的颜色相同时,显然有dp[i1][1]

    • 颜色不同时,将考虑的范围向前扩展到[i2k+3,ik+1],这时可以保证对于以[ik+1,i1]结尾的长度为k1的区间都被囊括其中,以下所有方法的合法性都可以用这个来解释

      • [i2k+3,ik+1]的颜色都相同时,[ik+2,i]的颜色可以取除了[i2k+3,ik+1]以外的任何颜色,这时就是dp[ik+1][1]×(c1)

      • [i2k+3,ik+1]颜色不同时,若两种颜色分别为ab,且ik+1的颜色为a[ik+2,i]的为b,这时就是dp[ik+1][2]

  • 对于dp[i][2]

    • [ik+1,i1]的颜色相同时,显然有i的颜色取值有除了[ik+1,i1]的颜色外的所有颜色,也就是dp[i1][1]×(c1)

    • [ik+1,i1]的颜色不同时,i的取值就有两种,这时有dp[i1][2]×2,但这并不合法,因为dp[i1][2]中包含了[ik+2,i1]的颜色都为a,而ik+1的颜色为b的方案数,所以考虑减去这种不合法的方案

      发现这种不合法的情况就是dp[i][1]的第二个大类,所以直接使用

综上:

dp[i][1]=dp[i1][1]+dp[ik+1][1]×(c1)+dp[ik+1][2]dp[i][2]=dp[i1][1]×(c1)+dp[i1][2]×2dp[ik+1][1]×(c1)dp[ik+1][2]

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e6+5,MOD=998244353;
int n,k,c;
ll dp[N][2],invf=499122177;
int main(){
	scanf("%d%d%d",&n,&k,&c);
	dp[1][1]=c%MOD;
	for(int i=2;i<=n;++i){
		dp[i][1]=((dp[i-1][1]+dp[max(0,i-k+1)][1]*(c-1)%MOD)%MOD+dp[max(0,i-k+1)][2])%MOD;
		dp[i][2]=((dp[i-1][1]*(c-1)%MOD+dp[i-1][2]*2%MOD)%MOD-(dp[max(0,i-k+1)][1]*(c-1)%MOD+dp[max(0,i-k+1)][2])%MOD+MOD)%MOD;
	}
	printf("%lld\n",(dp[n][1]+dp[n][2])%MOD); 
	return 0;
}
posted @   LuoyuSitfitw  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
点击右上角即可分享
微信分享提示