T9 Kuro and Topological Parity (CF979E)
T9 Kuro and Topological Parity (CF979E)
CF传送门
洛谷传送门
题意简述
给定
我们称一条好的路径为经过的点为黑白相间的路径,如果一个图好的路径的总数 %
数据范围
题解
这是 O(n) 的题解
这题在理解上有很多岔路,所以我会标出容易误解的地方
为了方便,“好的路径”基本都会用“路径”来代替
题意
解释一下,黑白相间指的是黑连向白,白连向黑
比如
- (一个也算!)
思路
首先第一眼,是跟奇偶性相关的计数问题
所以重心就落在了奇偶性上
然后发现加入的边必须从编号小的点指向编号大的点
显然是无环的,而且拓扑序就是顺序
直接dp好了
然而点也要选,边也要选,可能性太多了qwq
那我们先不要管点,只考虑连边
既然是按点dp,不妨来设想加入一个点,让前面的点向它连边
可是随机性太大了啊,所以要加状态来限制
首先能想到的就是颜色,要么是黑,要么是白
但这还不够。因为我们想统计的是路径数的奇偶性,而黑或白根本没有体现
所以还要再加上两种状态:连到这个点的路径总条数,要么是奇,要么是偶
综合起来,就是四种状态
- 注意不是加,是乘
为什么呢?
因为
而转移计算的是包含
两种情况互不干扰,可以理解成先选不包含
答案直接统计
注意事项
-
初始化
f[0][0][0][0]=1 -
别忘
long long ……
AC代码
#include<bits/stdc++.h>
using namespace std;
const long long N=1000000+5,mod=1e9+7;
long long n,p;
long long a[N],fx[N],f[N][2][2][2];
int main(){
scanf("%lld%lld",&n,&p);
for(long long i=1;i<=n;i++) scanf("%lld",&a[i]);
fx[0]=1;
for(long long i=1;i<=n;i++) fx[i]=fx[i-1]*2%mod;//预处理2^i
f[0][0][0][0]=1;//初始化
for(long long i=1;i<=n;i++)//枚举i
for(long long id=0;id<=1;id++)//枚举id
for(long long ob=0;ob<=1;ob++)//枚举ob
for(long long ow=0;ow<=1;ow++){//枚举ow
long long owo=f[i-1][id][ob][ow];//偷懒owo
if(a[i]!=0)//如果涂白
if(ob)//如果有奇黑
f[i][id][ob][ow]=(f[i][id][ob][ow]+fx[i-2]*owo%mod)%mod,//偶白
f[i][id^1][ob][1]=(f[i][id^1][ob][1]+fx[i-2]*owo%mod)%mod;//奇白(奇白就肯定为1了)
else
f[i][id^1][ob][1]=(f[i][id^1][ob][1]+fx[i-1]*owo%mod)%mod;//没有奇黑,只能转移到奇白
if(a[i]!=1)//如果涂黑
if(ow)//如果有奇白
f[i][id][ob][ow]=(f[i][id][ob][ow]+fx[i-2]*owo%mod)%mod,//偶黑
f[i][id^1][1][ow]=(f[i][id^1][1][ow]+fx[i-2]*owo%mod)%mod;//奇黑(奇黑就肯定为1了)
else
f[i][id^1][1][ow]=(f[i][id^1][1][ow]+fx[i-1]*owo%mod)%mod;//没有奇白,只能转移到奇黑
}
printf("%lld",(f[n][p][0][0]+f[n][p][0][1]+f[n][p][1][0]+f[n][p][1][1])%mod);
//直接计算答案
}