zoukankan      html  css  js  c++  java
  • [2020.11.13]CF704C Black Widow

    题意

    给出(n)个表达式,每个形如(v_i)或者(v_ior v_j)(v_i)为布尔变量,(-mle ile m)(i e0),其中(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_ior v_i)或者(v_ior 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;
    }
    
  • 相关阅读:
    吴军博士《浪潮之巅》
    第十二周
    第十一周
    第十周
    第九周
    第四次作业
    第四周
    学习进度表
    世界是数字的
    第二阶段团队第八天成果。
  • 原文地址:https://www.cnblogs.com/xryjr233/p/CF704C.html
Copyright © 2011-2022 走看看