题意
如果一个数组中有
的奇数回文串就是
.
数组中
的部分要求被替换成
的数字,最后得到的不
的数组有多少种
题解
如果能保证最小的奇数回文串不存在,就不会存在更大,最小的是
。
保证
。
我们可以发现分奇偶讨论。
每一部分都是
对于一个
的片段,
相同与否得到的答案不一样。
可以用
求解。
,
表示与左右不同,
表示与左不同,
表示与右不同。
对于左右不同的情况,转移是:
答案为
左右相同的时候比较简单,就不阐述了。
答案为
我们再分别计算片段,开头可以看做是左右相同的,但是这一片段答案是 ,因为最左边没有其他元素。
如果片段中的
为
呢,那么:
左右不同,则是
,答案为
左右相同,则是
,答案为
符合要求。
#include<bits/stdc++.h>
#define FOR(i,l,r) for(int i=l;i<=r;i++)
#define sf(x) scanf("%d",&x)
typedef long long ll;
using namespace std;
const ll mod = 998244353;
const int maxn = 2e5+500;
int n,k;
ll dp1[maxn][3],dp2[maxn][2];
vector<int>odd,even;
int A[maxn];
int main(){
cin>>n>>k;
dp1[0][1]=1;
dp1[0][0]=dp1[0][2]=0;
for(int i=1;i<=200050;i++){
dp1[i][0]=(dp1[i-1][1]*(k-2))%mod;
dp1[i][0]=(dp1[i][0]+dp1[i-1][2]*(k-2))%mod;
if(k>=3)dp1[i][0]=(dp1[i][0]+dp1[i-1][0]*(k-3))%mod;
dp1[i][1]=(dp1[i-1][2]+dp1[i-1][0])%mod;
dp1[i][2]=(dp1[i-1][1]+dp1[i-1][0])%mod;
}
dp2[0][1]=1;
dp2[0][0]=0;
for(int i=1;i<=200050;i++){
dp2[i][0]=(dp2[i][0]+dp2[i-1][1]*(k-1))%mod;
dp2[i][0]=(dp2[i][0]+dp2[i-1][0]*(k-2))%mod;
dp2[i][1]=(dp2[i-1][0])%mod;
}
ll l=0,r=0;
FOR(i,1,n){
scanf("%d",&A[i]);
if(i%2){
if(A[i]!=-1)odd.push_back(i);
}
else{
if(A[i]!=-1)even.push_back(i);
}
}
if(odd.size()){
l=(dp2[odd[0]/2][0]+dp2[odd[0]/2][1])%mod;
//cout<<l<<endl;
for(int i=0;i<odd.size()-1;i++){
int diff=odd[i+1]-odd[i];
diff=diff/2-1;
// cout<<diff<<endl;
if(A[odd[i]]==A[odd[i+1]]){
l=(l*dp2[diff][0])%mod;
}
else{
l=(l*(dp1[diff][0]+dp1[diff][1])%mod)%mod;
}
}
int g=(n-odd[odd.size()-1])/2;
if(g){
l=(l*(dp2[g][0]+dp2[g][1])%mod)%mod;
}
// cout<<l<<endl;
}
else{
l=k;
for(int i=3;i<=n;i+=2)l=(l*(k-1))%mod;
}
if(even.size()){
r=(dp2[even[0]/2-1][0]+dp2[even[0]/2-1][1])%mod;
for(int i=0;i<even.size()-1;i++){
int diff=even[i+1]-even[i];
diff=diff/2-1;
if(A[even[i]]==A[even[i+1]]){
r=(r*dp2[diff][0])%mod;
}
else{
r=(r*(dp1[diff][0]+dp1[diff][1])%mod)%mod;
}
}
//cout<<r<<endl;
int g=(n-even[even.size()-1])/2;
if(g){
r=(r*(dp2[g][0]+dp2[g][1])%mod)%mod;
}
//cout<<r<<endl;
}
else{
r=k;
for(int i=4;i<=n;i+=2)r=(r*(k-1))%mod;
}
cout<<(l*r)%mod<<endl;
}