题解-CF1140E Palindrome-less Arrays

CF1140E Palindrome-less Arrays

(n)(k)(n) 个数的序列 (a)。把 (a) 中的 (-1) 替换成 ([1,k]) 之间的整数。求使 (a) 中不存在长度为奇数的回文串的方案数。

数据范围:(2le n,kle 2cdot 10^5)(a_i=-1{ m~or~}a_iin[1,k])


题目限制即不能有 (a_i=a_{i-2})

(b_i=a_{2i},c_i=a_{2i-1})

答案为序列 (b)(c) 填成相邻两数不等的方案数积


如填 (x,-1,-1,...,-1,y) 这段 (i)(-1) 使相邻两数不等:

(f_i) 表示 (x=y) 的填法方案数,(g_i) 表示 (x ot=y) 的填法方案数。

[f_i= egin{cases} 0&(i=0)\ g_{i-1}(k-1)&{ m else}\ end{cases}\\ g_i= egin{cases} 1&(i=0)\ g_{i-1}(k-2)+f_{i-1}&{ m else}\ end{cases} ]

最后把每段 (-1) 的答案乘起来就是填 (b,c) 的方案数。

边界的处理具体看代码。


  • 代码
#include <bits/stdc++.h>
using namespace std;

//Start
typedef long long ll;
typedef double db;
#define mp(a,b) make_pair(a,b)
#define x first
#define y second
#define b(a) a.begin()
#define e(a) a.end()
#define sz(a) int((a).size())
#define pb(a) push_back(a)
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3f;

//Data
const int N=2e5;
const int mod=998244353;
int n,k,a[N+7];

//DP
int f[2][(N<<1)+7]; 
int bb,b[(N>>1)+7],cc,c[(N>>1)+7];
void Pre(){
	f[0][0]=0,f[1][0]=1;
	for(int i=1;i<=(n>>1)+1;i++){
		f[0][i]=(ll)f[1][i-1]*(k-1)%mod;
		f[1][i]=((ll)f[1][i-1]*(k-2)%mod+f[0][i-1])%mod;
	}
}
int DP(int cnt,int s[]){
	int len=0,lst=0,res=1;
	for(int i=1;i<=cnt;i++){
		if(s[i]==-1) len++;
		else {
			if(len){
				if(!lst) res=(ll(k-1)*f[1][len-1]+f[0][len-1])%mod*res%mod;
				else if(lst==s[i]) res=(ll)f[0][len]*res%mod;
				else res=(ll)f[1][len]*res%mod;
			}
			len=0,lst=s[i];
		}
	}
	if(len){
		if(!lst){
			if(len==1) res=k;
			else res=(ll(k-1)*f[1][len-2]+f[0][len-2])*k%mod*res%mod;
		} else res=(ll(k-1)*f[1][len-1]+f[0][len-1])%mod*res%mod;
	}
	return res;
}

//Main
int main(){
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		if(~a[i]&&i-2>=1&&a[i]==a[i-2]) return puts("0"),0;
		if(i&1) c[++cc]=a[i];
		else b[++bb]=a[i];
	}
	Pre();
	printf("%d
",(ll)DP(cc,c)*DP(bb,b)%mod);
	return 0;
}


祝大家学习愉快!

原文地址:https://www.cnblogs.com/George1123/p/12966010.html