CF1140E Palindrome-less Arrays(巧妙的递推)

Posted issue是fw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1140E Palindrome-less Arrays(巧妙的递推)相关的知识,希望对你有一定的参考价值。

LINK

题意

一个数组有些位置是 ? ? ?,你可以使用 [ 1 , k ] [1,k] [1,k]填充

满足最后对于 i ∈ [ 1 , n − 2 ] i\\in[1,n-2] i[1,n2] a i ! = a i + 2 a_i!=a_{i+2} ai!=ai+2,求方案数


我们分成奇数索引构成的数组和偶数索引构成的数组分别考虑

现在设奇数索引构成的数组为 a a a,条件限制相当于相邻元素值不能相同.

考虑到 ? ? ?可能连成一块,这就变得非常麻烦,其实可以把连续的 ? ? ?缩成一个块

f [ i ] [ 0 ] f[i][0] f[i][0]表示 ? ? ?块长度为 i i i,且问号块左右两端的数字不相等的方案, f [ i ] [ 1 ] f[i][1] f[i][1]表示两端相等

(注意这里的两端不是问号,是最左边问号左边那个确定的数字)

当从 f [ i − 1 ] [ 0 ] f[i-1][0] f[i1][0]转移来时,形如a -1 -1 -1…c ,在c前面插入一个数字 b b b变成 f [ i ] [ 0 ] f[i][0] f[i][0]

形如a -1 -1 -1 … b c,此时 b b b k − 2 k-2 k2种取值

当从 f [ i − 1 ] [ 1 ] f[i-1][1] f[i1][1]转移来时,形如a -1 -1 -1 … a.在最右边插入最右端的数字 b b b(已经被确定)变成a -1 -1 -1 … a b

那么倒数第一个问号只能取 a a a

f [ i ] [ 0 ] = f [ i − 1 ] [ 0 ] ∗ ( k − 2 ) + f [ i − 1 ] [ 1 ] f[i][0]=f[i-1][0]*(k-2)+f[i-1][1] f[i][0]=f[i1][0](k2)+f[i1][1]

f [ i ] [ 1 ] f[i][1] f[i][1]表示两端问号相等的方案

此时 f [ i − 1 ] [ 0 ] f[i-1][0] f[i1][0]形如a -1 -1 -1… b

考虑在最右边添上一个 a a a变成a -1 -1 -1… b a就变成了 f [ i ] [ 1 ] f[i][1] f[i][1]的方案

f [ i ] [ 1 ] = f [ i − 1 ] [ 0 ] ∗ ( k − 1 ) f[i][1]=f[i-1][0]*(k-1) f[i][1]=f[i1][0](k1)

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 3e5+10;
const int mod = 998244353;
int n,k,a[maxn],b[maxn],f[maxn][2];
int quick(int x,int n)
{
	int ans = 1;
	for( ; n ; n>>=1,x=x*x%mod )
		if( n&1 )	ans = ans*x%mod;
	return ans;
}
int solve(int a[],int n )
{
	if( !n )	return 1;
	int l = 1, r = n, ans = 0;
	while( l<=n && a[l]==-1 )	l++;
	while( r>=1 && a[r]==-1 )	r--;
	if( l>n )	return quick( k-1,n-1 )*k%mod;
	ans = quick( k-1,l-1 )*quick( k-1,n-r )%mod;
	int las = l;
	for(int i=l+1;i<=r;i++)
	{
		if( a[i]==-1 )	continue;
		else
		{
			ans = ans*f[i-las-1][a[las]==a[i]]%mod;
			las = i;
		}
	}	
	return ans;
}
signed main()
{
	cin >> n >> k;
	f[0][0] = 1, f[0][1] = 0;
	for(int i=1;i<=n;i++)
	{
		f[i][1] = f[i-1][0]*(k-1)%mod;
		f[i][0] = ( f[i-1][0]*(k-2)+f[i-1][1] )%mod;
	}
//	cout << f[2][0] << " --- " << f[2][1] << endl;
	for(int i=1;i<=n;i++)
	{
		int x; cin >> x;
		if( i&1 )	a[++a[0]] = x;
		else	b[++b[0]] = x;
	}
	cout << solve( a,a[0] )*solve( b,b[0] )%mod;
}

以上是关于CF1140E Palindrome-less Arrays(巧妙的递推)的主要内容,如果未能解决你的问题,请参考以下文章

CF1140E Palindrome-less Arrays(巧妙的递推)

codeforces 1140E Palindrome-less Arrays

CodeForces - 1140E Palindrome-less Arrays

Cardiogram - CF435C 模拟

Skills - CF613B

总之就是 CF 1536 A & B