题目大意:给你一个逻辑表达式,然后让你计算表达式为真的取值情况数,表达式由一系列的 a 或者 a|b 亦或起来,每个变量最多出现两次(包括反变量)
嘴炮开始:每个变量最多出现两次,那么跟它相关联的变量也最多是两个,转化成图的话,那么整个图就是由很多链和很多环组成,分别DP就好了;
链DP很简单,从一段DP到另一端就可以了
环上的DP就是先确定一个点的值然后链DP就好了,一个环DP两次
写起来感觉还是有点麻烦。。
#include<cstdio> #include<vector> #include<cstring> #include<algorithm> using namespace std; const int mod=1e9+7; const int maxn=100100*2; int n,m,d[maxn]; int fir[maxn],last[maxn<<2],nex[maxn<<2],a[maxn<<2],b[maxn<<2],tot=1; vector <int> e[maxn]; bool vis[maxn]; long long dp[maxn][2][2]; int sgn(int x) { if(x>0)return 0; if(x<0)return 1; } void add(int u,int v,int aa,int bb) { ++tot; last[tot]=v; a[tot]=aa; b[tot]=bb; nex[tot]=fir[u]; fir[u]=tot; } struct node{ int a,b; }fa[maxn]; bool evis[maxn<<2]; int s[maxn],cnt; void dfs(int x) { //printf("%d ",x); vis[x]=1; s[++cnt]=x; for(int i = fir[x];i;i=nex[i]) { if(!evis[i]) { evis[i]=1; evis[i^1]=1; fa[x]=(node){a[i],b[i]}; if(!vis[last[i]])dfs(last[i]); } } } void up(long long &a,long long b) { a+=b; a%=mod; } int main() { scanf("%d%d",&n,&m); long long ans1=0,ans0=1; for(int i = 1;i <= n;i++) { int k; scanf("%d",&k); if(k==1) { int x; scanf("%d",&x); e[abs(x)].push_back(sgn(x)); } else { int u,v; scanf("%d%d",&u,&v); if(abs(u)==abs(v)) { if(u!=v) { vis[abs(u)]=1; swap(ans1,ans0); ans1=ans1*2%mod; ans0=ans0*2%mod; } else { e[abs(u)].push_back(sgn(u)); } continue; } add(abs(u),abs(v),sgn(u),sgn(v)); add(abs(v),abs(u),sgn(v),sgn(u)); d[abs(u)]++; d[abs(v)]++; } } for(int i = 1;i <= m;i++) if(!vis[i] && d[i]==0 && e[i].size()>0) { vis[i]=1; if(e[i].size()==1) { ans1=(ans1+ans0)%mod; ans0=ans1; } else { if(e[i][0]==e[i][1]) { ans1=ans1*2%mod; ans0=ans0*2%mod; } else { swap(ans1,ans0); ans1=ans1*2%mod; ans0=ans0*2%mod; } } //printf("%I64d %I64d ",ans1,ans0); } for(int i = 1;i <= m;i++) if(d[i]==1 && !vis[i]) { cnt=0; dfs(i); dp[i][0][0]=1; dp[i][0][1]=0; dp[i][1][0]=1; dp[i][1][1]=0; if(e[i].size()) { if(e[i][0]==1) { swap(dp[i][0][0],dp[i][0][1]); } else { swap(dp[i][1][0],dp[i][1][1]); } } for(int step = 1;step < cnt;step++) { for(int ii = 0;ii < 2;ii++) for(int jj = 0;jj < 2;jj++) for(int kk = 0;kk < 2;kk++) { up(dp[s[step+1]][kk][((ii^fa[s[step]].a)|(kk^fa[s[step]].b))^jj],dp[s[step]][ii][jj]); } } int x=s[cnt]; if(e[x].size()) { if(e[x][0]==1) { swap(dp[x][0][0],dp[x][0][1]); } else { swap(dp[x][1][0],dp[x][1][1]); } } //printf("xx %I64d %I64d %I64d %I64d ",dp[x][0][0],dp[x][0][1],dp[x][1][0],dp[x][1][1]); long long a1=0,a0=0; //printf("%I64d %I64d ",ans1,ans0); a1=(dp[x][0][0]+dp[x][1][0])*ans1%mod+(dp[x][0][1]+dp[x][1][1])*ans0%mod; a0=(dp[x][0][0]+dp[x][1][0])*ans0%mod+(dp[x][0][1]+dp[x][1][1])*ans1%mod; ans1=a1%mod; ans0=a0%mod; //printf("%I64d %I64d ",ans1,ans0); } for(int i = 1;i <= m;i++) if(d[i]==2 && !vis[i]) { cnt=0; dfs(i); dp[i][0][0]=1; dp[i][0][1]=0; dp[i][1][0]=0; dp[i][1][1]=0; for(int step = 2;step <= cnt;step++) memset(dp[s[step]],0,sizeof(dp[s[step]])); for(int step = 1;step < cnt;step++) { for(int ii = 0;ii < 2;ii++) for(int jj = 0;jj < 2;jj++) for(int kk = 0;kk < 2;kk++) { up(dp[s[step+1]][kk][((ii^fa[s[step]].a)|(kk^fa[s[step]].b))^jj],dp[s[step]][ii][jj]); } } int x=s[cnt]; for(int ii=0;ii<2;ii++) if((ii^fa[x].a)|(fa[x].b))swap(dp[x][ii][0],dp[x][ii][1]); long long a1=0,a0=0; //printf("xx %I64d %I64d %I64d %I64d ",dp[x][0][0],dp[x][0][1],dp[x][1][0],dp[x][1][1]); a1+=(dp[x][0][0]+dp[x][1][0])*ans1%mod+(dp[x][0][1]+dp[x][1][1])*ans0%mod; a0+=(dp[x][0][0]+dp[x][1][0])*ans0%mod+(dp[x][0][1]+dp[x][1][1])*ans1%mod; dp[i][0][0]=0; dp[i][0][1]=0; dp[i][1][0]=1; dp[i][1][1]=0; for(int step = 2;step <= cnt;step++) memset(dp[s[step]],0,sizeof(dp[s[step]])); for(int step = 1;step < cnt;step++) { for(int ii = 0;ii < 2;ii++) for(int jj = 0;jj < 2;jj++) for(int kk = 0;kk < 2;kk++) { up(dp[s[step+1]][kk][((ii^fa[s[step]].a)|(kk^fa[s[step]].b))^jj],dp[s[step]][ii][jj]); } } for(int ii=0;ii<2;ii++) if((ii^fa[x].a)|(1^fa[x].b))swap(dp[x][ii][0],dp[x][ii][1]); //printf("xx %I64d %I64d %I64d %I64d ",dp[x][0][0],dp[x][0][1],dp[x][1][0],dp[x][1][1]); a1+=(dp[x][0][0]+dp[x][1][0])*ans1%mod+(dp[x][0][1]+dp[x][1][1])*ans0%mod; a0+=(dp[x][0][0]+dp[x][1][0])*ans0%mod+(dp[x][0][1]+dp[x][1][1])*ans1%mod; ans1=a1%mod; ans0=a0%mod; //printf("%I64d %I64d ",ans1,ans0); } for(int i = 1;i <= m;i++) if(!vis[i])ans1=ans1*2%mod; printf("%I64d ",ans1); return 0; }