给定 N、M、K(N<=10^6),求有多少种给 N 个物品染色的方式,使得至少有一个子段满足染色为 G 的有连续 M 个,染色为 R 的至多连续 K 个。每个物品必须染色成 R、G、B 中的一种。
条件“至少一个子段满足有连续M个”不方便转移,可以转化为 至多有 N 个连续的的方案 减去 至多有 M-1 个连续的的方案。
那么两问统一成一个问题:求染色为 X 的至多连续 K 个的方案数。
接下来就考虑分情况讨论递推。假设当前为第 i 个物品,且之前的序列符合要求
那么根据第三种情况,可以发现当在DP状态中设置“颜色”这一维度时有利于递推。
于是设状态 dp[i][0~2] 表示第 i 个物品染色为 0~2 中的某一种时的合法方案总数。递推就根据之前的分类讨论来就行啦。
long long Solve(int u,int v){
f[0][0]=1;f[0][1]=f[0][2]=0;
for(int i=1;i<=n;++i){
long long sum=(f[i-1][0]+f[i-1][1]+f[i-1][2])%Mod;
f[i][2]=sum;
if(i<=u) f[i][0]=sum;
else if(i==u+1) f[i][0]=sum-1;
else if(i>u+1) f[i][0]=(sum-f[i-u-1][1]-f[i-u-1][2]+Mod+Mod)%Mod;
if(i<=v) f[i][1]=sum;
else if(i==v+1) f[i][1]=sum-1;
else if(i>v+1) f[i][1]=(sum-f[i-v-1][0]-f[i-v-1][2]+Mod+Mod)%Mod;
}
return (f[n][0]+f[n][1]+f[n][2])%Mod;
}
遇到计数题目时,先对条件逐一思考,遇到刁钻的条件可以考虑转化来求解。
在转移时,通常进行分类讨论。可以先分类讨论,分析出在什么情况下自己需要那些信息来推出当前信息,并据此来设置状态转移方程。
原文:https://www.cnblogs.com/parauni-blog/p/13060680.html