6553. 【GDOI2020模拟4.11】人生(life)
题目描述
题解
首先写一个O(n^5)的dp
然后优化到O(n)
设f[i,j1,j2,k1,k2]表示从后往前做到i,其中以白色开头的路径条数%2为01的个数j1j2,k1k2同理
然后可以发现一个点路径条数=1-(连向不同颜色的条数为1的个数%2)
同颜色以及0的不会影响,不同颜色的1的等于组合数取奇/偶之和,显然如果有>=1个则结果01均分,否则只有1
所以只用记每种颜色是否有路径%2为1的即可O(n)
code
#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define mod 998244353
#define ll long long
#define file
using namespace std;
ll f[2][2][2][2],p[200001],ans;
int a[200001],n,i2,i,j,k,l,I,I2,s;
int main()
{
freopen("life.in","r",stdin);
#ifdef file
freopen("life.out","w",stdout);
#endif
scanf("%d",&n);
fo(i,1,n) scanf("%d",&a[i]);
p[0]=1;
fo(i,1,n) p[i]=p[i-1]*2%mod;
I=0;f[I][0][0][0]=1;
fd(i2,n,1)
{
I2=I^1;
fo(j,0,1)
{
fo(k,0,1)
{
fo(l,0,1)
if (f[I][j][k][l])
{
fo(s,0,1)
if (a[i2]==-1 || s==a[i2])
{
if (!s)
{
if (!k)
f[I2][1][k][l^1]=(f[I2][1][k][l^1]+f[I][j][k][l]*p[n-i2])%mod;
else
f[I2][j][k][l]=(f[I2][j][k][l]+f[I][j][k][l]*p[(n-i2)-1])%mod,
f[I2][1][k][l^1]=(f[I2][1][k][l^1]+f[I][j][k][l]*p[(n-i2)-1])%mod;
}
else
{
if (!j)
f[I2][j][1][l^1]=(f[I2][j][1][l^1]+f[I][j][k][l]*p[n-i2])%mod;
else
f[I2][j][k][l]=(f[I2][j][k][l]+f[I][j][k][l]*p[(n-i2)-1])%mod,
f[I2][j][1][l^1]=(f[I2][j][1][l^1]+f[I][j][k][l]*p[(n-i2)-1])%mod;
}
}
}
}
}
memset(f[I],0,sizeof(f[I]));
I=I2;
}
fo(j,0,1)
{
fo(k,0,1)
ans=(ans+f[I][j][k][1])%mod;
}
printf("%lld\n",ans);
fclose(stdin);
fclose(stdout);
return 0;
}