题目链接:https://codeforces.com/contest/1140/problem/E
题目大意
给定一个串,不能出现长度为奇数 ( l e n ≥ 3 ) (len\geq3) (len≥3)的回文串, − 1 -1 −1的位置可以填 1 − k 1-k 1−k的所有数,问有多少种合法的方案,输出方案数。
题解思路
思路来源于官方题解,看完就是恍然大悟的感觉。
不能出现长度为奇数
(
l
e
n
≥
3
)
(len\geq3)
(len≥3)的回文串
=
=
=没有长度为
3
3
3的回文串
这样就可以分奇偶两个串,相邻的两个数不相同。
通过枚举可以发现,一个连续的 − 1 -1 −1串对答案的贡献只和 k k k以及左右两个数是否相等有关,和左右两个数的具体值无关
我用 d p [ l e n ] [ 0 / 1 ] dp[len][0/1] dp[len][0/1]表示长度为 l e n len len的 − 1 -1 −1串对答案的贡献, 0 0 0表示串左右两个数相同 1 1 1表示左右两个数不同
比较懒,应该写个函数的,直接复制了一遍
这是我做的时候随便写的样例,可以发现:
d
p
[
i
]
[
1
]
dp[i][1]
dp[i][1]的组成来源于上一长度中在
[
1
,
k
]
[1,k]
[1,k]中不为当前数的状态和
就是
d
p
[
i
−
1
]
[
0
]
∗
(
k
−
1
)
dp[i-1][0]*(k-1)
dp[i−1][0]∗(k−1)
d
p
[
i
]
[
0
]
dp[i][0]
dp[i][0]的组成来源于上一长度中在
[
1
−
k
]
[1-k]
[1−k]中不为当前数的状态和
就是
d
p
[
i
−
1
]
[
1
]
+
d
p
[
i
−
1
]
[
0
]
∗
(
k
−
2
)
dp[i-1][1]+dp[i-1][0]*(k-2)
dp[i−1][1]+dp[i−1][0]∗(k−2)
另外还要单独考虑:
1.全为
−
1
-1
−1的情况,第一个位置有
k
k
k种选择,后面的都有
k
−
1
k-1
k−1种选择,对答案的贡献就是
k
∗
(
k
−
1
)
l
e
n
−
1
k*(k-1)^{len-1}
k∗(k−1)len−1
2.只有一边有约束的情况,临近约束的点有
k
−
1
k-1
k−1种选择,后面每个数都有
k
−
1
k-1
k−1种选择,对答案的贡献是
(
k
−
1
)
l
e
n
(k-1)^{len}
(k−1)len
每一部分的贡献都是乘在 a n s ans ans上的(相互独立)
#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
#define int ll
#define debug cout<<"fuck"<<endl;
#define pb push_back
const int mod=(int)998244353;
const int maxn=(int)2e5+5;
int m[maxn];
int dp[maxn][2];
vector<int>a,b;
ll quick_pow_mod(ll a,ll b,ll c)
{
ll res=1;
while(b)
{
if(b & 1)
{
res=(res*a)%c;
}
a=(a*a)%c;
b=b>>1;
}
return res;
}
int n,k;
void init()
{
//0表示不同,1表示相同
dp[1][1]=k-1;
dp[1][0]=k-2;
for(int i=2;i<maxn;i++)
{
dp[i][1]=(dp[i-1][0]*(k-1))%mod;
dp[i][0]=(dp[i-1][1]+dp[i-1][0]*(k-2))%mod;
}
}
signed main()
{
IOS
bool fail=0;
cin>>n>>k;
init();
/*for(int i=1;i<=5;i++)
{
cout<<dp[i][0]<<' '<<dp[i][1]<<endl;
}*/
for(int i=1;i<=n;i++)
{
cin>>m[i];
if(i%2)a.pb(m[i]);
else b.pb(m[i]);
if(m[i]!=-1&&i>=3&&m[i]==m[i-2])
{
fail=1;
}
}
if(fail==1)
{
cout<<0<<endl;
return 0;
}
int flag;
ll ans=1;
for(int i=0;i<a.size();i++)
{
int len=0;
if(a[i]==-1&&i==0)
{
len=1;
while(a[i+1]==-1&&i+1<a.size())
{
i++;
len++;
}
if(len==a.size())
{
ans*=k*quick_pow_mod(k-1,len-1,mod);
ans%=mod;
break;
}
else
{
ans*=quick_pow_mod(k-1,len,mod);
ans%=mod;
continue;
}
}
else if(a[i]==-1&&i>=1)
{
int pre=a[i-1];
len=1;
while(a[i+1]==-1&&i+1<a.size())
{
i++;
len++;
}
if(i==a.size()-1)
{
ans*=quick_pow_mod(k-1,len,mod);
ans%=mod;
}
else
{
if(a[i+1]==pre)
{
ans*=dp[len][1];
ans%=mod;
}
else
{
ans*=dp[len][0];
ans%=mod;
}
}
}
}
for(int i=0;i<b.size();i++)
{
int len=0;
if(b[i]==-1&&i==0)
{
len=1;
while(b[i+1]==-1&&i+1<b.size())
{
i++;
len++;
}
if(len==b.size())
{
ans*=k*quick_pow_mod(k-1,len-1,mod);
ans%=mod;
break;
}
else
{
ans*=quick_pow_mod(k-1,len,mod);
ans%=mod;
continue;
}
}
else if(b[i]==-1&&i>=1)
{
int pre=b[i-1];
len=1;
while(b[i+1]==-1&&i+1<b.size())
{
i++;
len++;
}
if(i==b.size()-1)
{
ans*=quick_pow_mod(k-1,len,mod);
ans%=mod;
}
else
{
if(b[i+1]==pre)
{
ans*=dp[len][1];
ans%=mod;
}
else
{
ans*=dp[len][0];
ans%=mod;
}
}
}
}
cout<<ans<<endl;
return 0;
}