分析
我们不难发现对于偶数的情况只要相邻两个数不相等即可
而对于奇数的情况只要中间恰好隔一个数的两个数不相等即可
于是我们又dp[i][0/1]表示考虑到第i位,这一位和它后面离它最近的一个确定的数是否相等
每次从i-1转移即可
注意对于奇数的情况最终答案要n-1和n的dp值相乘以保证合法
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
const int mod = 998244353;
int dp[200100][2],a[200100],b[200100],n,m,k;
int main(){
int i,j;
scanf("%d%d%d",&n,&k,&m);
for(i=1;i<=n;i++)scanf("%d",&a[i]);
if(m==0){
for(i=n-1;i>0;i--)b[i]=a[i+1]?a[i+1]:b[i+1];
if(a[1]&&a[1]==b[1]){
dp[1][0]=0;
dp[1][1]=1;
}else if(a[1]){
dp[1][1]=0;
dp[1][0]=1;
}else {
dp[1][1]=1;
dp[1][0]=k-1;
}
for(i=2;i<=n;i++)
if(a[i]&&a[i]==b[i]){
dp[i][0]=0;
dp[i][1]=dp[i-1][0];
}else if(a[i]){
dp[i][1]=0;
dp[i][0]=dp[i-1][0];
}else {
dp[i][1]=dp[i-1][0];
dp[i][0]=((dp[i][0]+1ll*dp[i-1][0]*(k-2)%mod)%mod+1ll*dp[i-1][1]*(k-1)%mod)%mod;
}
printf("%d
",(dp[n][0]+dp[n][1])%mod);
}else {
for(i=n-2;i>0;i--)b[i]=a[i+2]?a[i+2]:b[i+2];
for(i=1;i<=2;i++){
if(a[i]&&a[i]==b[i]){
dp[i][0]=0;
dp[i][1]=1;
}else if(a[i]){
dp[i][1]=0;
dp[i][0]=1;
}else {
dp[i][1]=1;
dp[i][0]=k-1;
}
}
for(i=3;i<=n;i++)
if(a[i]&&a[i]==b[i]){
dp[i][0]=0;
dp[i][1]=dp[i-2][0];
}else if(a[i]){
dp[i][1]=0;
dp[i][0]=dp[i-2][0];
}else {
dp[i][1]=dp[i-2][0];
dp[i][0]=((dp[i][0]+1ll*dp[i-2][0]*(k-2)%mod)%mod+1ll*dp[i-2][1]*(k-1)%mod)%mod;
}
printf("%d
",1ll*((dp[n][0]+dp[n][1])%mod)*((dp[n-1][0]+dp[n-1][1])%mod)%mod);
}
return 0;
}