[2020.11.13]CF704C Black Widow

题意

给出\(n\)个表达式,每个形如\(v_i\)或者\(v_i\or v_j\)\(v_i\)为布尔变量,\(-m\le i\le m\)\(i\ne0\),其中\(v_{-i}=!v_i\),求使得共有奇数个式子值为真的\(v\)的取值的方案数。

保证\(v_{-i}\)\(v_i\)在所有表达式中一共出现不超过\(2\)次。

题解

如果某个\(v_i\)出现了\(2\)次,就把它所在的两个表达式之间连一条边。

那么现在这个图应该形如若干条链和若干个环。可以对于每个环/链单独做。

对于链,可以从开头开始dp,记\(f_{i,j,k}\)表示考虑链上前\(i\)个式子,第\(i\)个式子和第\(i+1\)个式子之间的变量取值为\(j\),有\(k\)个式子为真的方案数。

对于环,可以枚举环上某个变量的取值,然后和链一样做。

最后把所有环和链的结果合并,注意特判没有出现的变量和形如\(v_i\or v_i\)或者\(v_i\or v_{-i}\)的式子即可。

code:

#include<bits/stdc++.h>
#define ci const int&
#define pi pair<int,int>
#define f first
#define s second
using namespace std;
const int mod=1e9+7;
int n,m,k[100010],v[100010][2],av[100010][2],ap[100010],in[100010][2],vis[100010],tg[100010],cnt;
pi ans,res[100010],dp[100010][2];
vector<int>lk[100010];
int Nx(ci x,ci y){
	return in[x][in[x][0]==y];
}
void dfs(ci x,ci lv,vector<int>&l){
	vis[x]=1,l.push_back(x);
	if(av[x][0]!=lv)swap(av[x][0],av[x][1]),swap(v[x][0],v[x][1]);
	if(ap[av[x][1]]==2)dfs(Nx(av[x][1],x),av[x][1],l);
}
void dfs2(ci x,ci lv,ci sv,vector<int>&l){
	vis[x]=1,l.push_back(x);
	if(av[x][0]!=lv)swap(av[x][0],av[x][1]),swap(v[x][0],v[x][1]);
	if(av[x][1]!=sv)dfs2(Nx(av[x][1],x),av[x][1],sv,l);
}
pi op(pi x,pi y){
	return(pi){(1ll*x.f*y.f+1ll*x.s*y.s)%mod,(1ll*x.f*y.s+1ll*x.s*y.f)%mod};
}
int val(ci x,ci v1,ci v2){
	return (v1^(v[x][0]<0))|(v2^(v[x][1]<0));
}
void Add(int&x,ci y){
	(x+=y)>=mod?x-=mod:0;
}
pi Calc(ci x){
	if(!tg[x]){
		dp[0][0].f=1,dp[0][1].f=(k[lk[x][0]]==2),dp[0][0].s=dp[0][1].s=0;
		for(int i=0;i<lk[x].size();++i){
			dp[i+1][0]=dp[i+1][1]=(pi){0,0};
			if(val(lk[x][i],0,0))Add(dp[i+1][0].f,dp[i][0].s),Add(dp[i+1][0].s,dp[i][0].f);
			else Add(dp[i+1][0].f,dp[i][0].f),Add(dp[i+1][0].s,dp[i][0].s);
			if(val(lk[x][i],1,0))Add(dp[i+1][0].f,dp[i][1].s),Add(dp[i+1][0].s,dp[i][1].f);
			else Add(dp[i+1][0].f,dp[i][1].f),Add(dp[i+1][0].s,dp[i][1].s);
			if(i!=lk[x].size()-1||k[lk[x][lk[x].size()-1]]==2){
				if(val(lk[x][i],0,1))Add(dp[i+1][1].f,dp[i][0].s),Add(dp[i+1][1].s,dp[i][0].f);
				else Add(dp[i+1][1].f,dp[i][0].f),Add(dp[i+1][1].s,dp[i][0].s);
				if(val(lk[x][i],1,1))Add(dp[i+1][1].f,dp[i][1].s),Add(dp[i+1][1].s,dp[i][1].f);
				else Add(dp[i+1][1].f,dp[i][1].f),Add(dp[i+1][1].s,dp[i][1].s);
			}
		}
		return(pi){(dp[lk[x].size()][0].f+dp[lk[x].size()][1].f)%mod,(dp[lk[x].size()][0].s+dp[lk[x].size()][1].s)%mod};
	}else{
		pi ret;
		dp[0][0].f=1,dp[0][1].f=dp[0][0].s=dp[0][1].s=0;
		for(int i=0;i<lk[x].size();++i){
			dp[i+1][0]=dp[i+1][1]=(pi){0,0};
			if(val(lk[x][i],0,0))Add(dp[i+1][0].f,dp[i][0].s),Add(dp[i+1][0].s,dp[i][0].f);
			else Add(dp[i+1][0].f,dp[i][0].f),Add(dp[i+1][0].s,dp[i][0].s);
			if(val(lk[x][i],1,0))Add(dp[i+1][0].f,dp[i][1].s),Add(dp[i+1][0].s,dp[i][1].f);
			else Add(dp[i+1][0].f,dp[i][1].f),Add(dp[i+1][0].s,dp[i][1].s);
			if(i!=lk[x].size()-1){
				if(val(lk[x][i],0,1))Add(dp[i+1][1].f,dp[i][0].s),Add(dp[i+1][1].s,dp[i][0].f);
				else Add(dp[i+1][1].f,dp[i][0].f),Add(dp[i+1][1].s,dp[i][0].s);
				if(val(lk[x][i],1,1))Add(dp[i+1][1].f,dp[i][1].s),Add(dp[i+1][1].s,dp[i][1].f);
				else Add(dp[i+1][1].f,dp[i][1].f),Add(dp[i+1][1].s,dp[i][1].s);
			}
		}
		ret=(pi){dp[lk[x].size()][0].f+dp[lk[x].size()][1].f,dp[lk[x].size()][0].s+dp[lk[x].size()][1].s};
		dp[0][1].f=1,dp[0][0].f=dp[0][0].s=dp[0][1].s=0;
		for(int i=0;i<lk[x].size();++i){
			dp[i+1][0]=dp[i+1][1]=(pi){0,0};
			if(i!=lk[x].size()-1){
				if(val(lk[x][i],0,0))Add(dp[i+1][0].f,dp[i][0].s),Add(dp[i+1][0].s,dp[i][0].f);
				else Add(dp[i+1][0].f,dp[i][0].f),Add(dp[i+1][0].s,dp[i][0].s);
				if(val(lk[x][i],1,0))Add(dp[i+1][0].f,dp[i][1].s),Add(dp[i+1][0].s,dp[i][1].f);
				else Add(dp[i+1][0].f,dp[i][1].f),Add(dp[i+1][0].s,dp[i][1].s);
			}
			if(val(lk[x][i],0,1))Add(dp[i+1][1].f,dp[i][0].s),Add(dp[i+1][1].s,dp[i][0].f);
			else Add(dp[i+1][1].f,dp[i][0].f),Add(dp[i+1][1].s,dp[i][0].s);
			if(val(lk[x][i],1,1))Add(dp[i+1][1].f,dp[i][1].s),Add(dp[i+1][1].s,dp[i][1].f);
			else Add(dp[i+1][1].f,dp[i][1].f),Add(dp[i+1][1].s,dp[i][1].s);
		}
		return(pi){(1ll*ret.f+dp[lk[x].size()][0].f+dp[lk[x].size()][1].f)%mod,(1ll*ret.s+dp[lk[x].size()][0].s+dp[lk[x].size()][1].s)%mod};
	}
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i){
		scanf("%d",&k[i]);
		for(int j=0;j<k[i];++j)scanf("%d",&v[i][j]),av[i][j]=abs(v[i][j]),in[av[i][j]][ap[av[i][j]]++]=i;
	}
	for(int i=1;i<=n;++i)if(!vis[i]){
		if(k[i]==1&&ap[av[i][0]]==1)vis[i]=1,res[++cnt].f=1,res[cnt].s=1;
		else if(av[i][0]==av[i][1])vis[i]=1,res[++cnt].s=1+(v[i][0]!=v[i][1]),res[cnt].f=2-res[cnt].s;
		else if((ap[av[i][0]]==2)+(ap[av[i][1]]==2)!=2){
			vis[i]=1;
			if(ap[av[i][0]]==2)swap(av[i][0],av[i][1]),swap(v[i][0],v[i][1]);
			if(ap[av[i][1]]==2)++cnt,dfs(i,av[i][0],lk[cnt]);
			else res[++cnt].f=1,res[cnt].s=3;
		}
	}
	for(int i=1;i<=n;++i)if(!vis[i])tg[++cnt]=1,lk[cnt].push_back(i),dfs2(Nx(av[i][1],i),av[i][1],av[i][0],lk[cnt]);
	ans.f=1;
	for(int i=1;i<=cnt;++i){
		if(!res[i].s)res[i]=Calc(i);
		ans=op(ans,res[i]);
	}
	for(int i=1;i<=m;++i)if(!ap[i])(ans.s<<=1)>=mod?ans.s-=mod:0;
	printf("%d",ans.s);
	return 0;
}
posted @ 2020-11-14 09:00  xryjr233  阅读(152)  评论(0编辑  收藏  举报