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;
}
posted @ 2020-04-13 15:34  gmh77  阅读(192)  评论(0编辑  收藏  举报