题目大意:给你一个逻辑表达式,然后让你计算表达式为真的取值情况数,表达式由一系列的 a 或者 a|b 亦或起来,每个变量最多出现两次(包括反变量)

嘴炮开始:每个变量最多出现两次,那么跟它相关联的变量也最多是两个,转化成图的话,那么整个图就是由很多链和很多环组成,分别DP就好了;

链DP很简单,从一段DP到另一端就可以了

环上的DP就是先确定一个点的值然后链DP就好了,一个环DP两次

写起来感觉还是有点麻烦。。

#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std; const int mod=1e9+;
const int maxn=*;
int n,m,d[maxn];
int fir[maxn],last[maxn<<],nex[maxn<<],a[maxn<<],b[maxn<<],tot=;
vector <int> e[maxn];
bool vis[maxn];
long long dp[maxn][][]; int sgn(int x)
{
if(x>)return ;
if(x<)return ;
} 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<<];
int s[maxn],cnt; void dfs(int x)
{
//printf("%d\n",x);
vis[x]=;
s[++cnt]=x;
for(int i = fir[x];i;i=nex[i])
{
if(!evis[i])
{
evis[i]=;
evis[i^]=;
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=,ans0=;
for(int i = ;i <= n;i++)
{
int k;
scanf("%d",&k);
if(k==)
{
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)]=;
swap(ans1,ans0);
ans1=ans1*%mod;
ans0=ans0*%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 = ;i <= m;i++)
if(!vis[i] && d[i]== && e[i].size()>)
{
vis[i]=;
if(e[i].size()==)
{
ans1=(ans1+ans0)%mod;
ans0=ans1;
}
else
{
if(e[i][]==e[i][])
{
ans1=ans1*%mod;
ans0=ans0*%mod;
}
else
{
swap(ans1,ans0);
ans1=ans1*%mod;
ans0=ans0*%mod;
}
}
//printf("%I64d %I64d\n",ans1,ans0);
}
for(int i = ;i <= m;i++)
if(d[i]== && !vis[i])
{
cnt=;
dfs(i);
dp[i][][]=;
dp[i][][]=;
dp[i][][]=;
dp[i][][]=;
if(e[i].size())
{
if(e[i][]==)
{
swap(dp[i][][],dp[i][][]);
}
else
{
swap(dp[i][][],dp[i][][]);
}
}
for(int step = ;step < cnt;step++)
{
for(int ii = ;ii < ;ii++)
for(int jj = ;jj < ;jj++)
for(int kk = ;kk < ;kk++)
{
up(dp[s[step+]][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][]==)
{
swap(dp[x][][],dp[x][][]);
}
else
{
swap(dp[x][][],dp[x][][]);
}
}
//printf("xx %I64d %I64d %I64d %I64d\n",dp[x][0][0],dp[x][0][1],dp[x][1][0],dp[x][1][1]);
long long a1=,a0=; //printf("%I64d %I64d\n",ans1,ans0);
a1=(dp[x][][]+dp[x][][])*ans1%mod+(dp[x][][]+dp[x][][])*ans0%mod;
a0=(dp[x][][]+dp[x][][])*ans0%mod+(dp[x][][]+dp[x][][])*ans1%mod;
ans1=a1%mod;
ans0=a0%mod;
//printf("%I64d %I64d\n",ans1,ans0);
}
for(int i = ;i <= m;i++)
if(d[i]== && !vis[i])
{
cnt=;
dfs(i);
dp[i][][]=;
dp[i][][]=;
dp[i][][]=;
dp[i][][]=;
for(int step = ;step <= cnt;step++)
memset(dp[s[step]],,sizeof(dp[s[step]]));
for(int step = ;step < cnt;step++)
{
for(int ii = ;ii < ;ii++)
for(int jj = ;jj < ;jj++)
for(int kk = ;kk < ;kk++)
{
up(dp[s[step+]][kk][((ii^fa[s[step]].a)|(kk^fa[s[step]].b))^jj],dp[s[step]][ii][jj]);
}
}
int x=s[cnt];
for(int ii=;ii<;ii++)
if((ii^fa[x].a)|(fa[x].b))swap(dp[x][ii][],dp[x][ii][]);
long long a1=,a0=;
//printf("xx %I64d %I64d %I64d %I64d\n",dp[x][0][0],dp[x][0][1],dp[x][1][0],dp[x][1][1]);
a1+=(dp[x][][]+dp[x][][])*ans1%mod+(dp[x][][]+dp[x][][])*ans0%mod;
a0+=(dp[x][][]+dp[x][][])*ans0%mod+(dp[x][][]+dp[x][][])*ans1%mod; dp[i][][]=;
dp[i][][]=;
dp[i][][]=;
dp[i][][]=;
for(int step = ;step <= cnt;step++)
memset(dp[s[step]],,sizeof(dp[s[step]]));
for(int step = ;step < cnt;step++)
{
for(int ii = ;ii < ;ii++)
for(int jj = ;jj < ;jj++)
for(int kk = ;kk < ;kk++)
{
up(dp[s[step+]][kk][((ii^fa[s[step]].a)|(kk^fa[s[step]].b))^jj],dp[s[step]][ii][jj]);
}
}
for(int ii=;ii<;ii++)
if((ii^fa[x].a)|(^fa[x].b))swap(dp[x][ii][],dp[x][ii][]);
//printf("xx %I64d %I64d %I64d %I64d\n",dp[x][0][0],dp[x][0][1],dp[x][1][0],dp[x][1][1]);
a1+=(dp[x][][]+dp[x][][])*ans1%mod+(dp[x][][]+dp[x][][])*ans0%mod;
a0+=(dp[x][][]+dp[x][][])*ans0%mod+(dp[x][][]+dp[x][][])*ans1%mod;
ans1=a1%mod;
ans0=a0%mod;
//printf("%I64d %I64d\n",ans1,ans0);
}
for(int i = ;i <= m;i++)
if(!vis[i])ans1=ans1*%mod;
printf("%I64d\n",ans1);
return ;
}

AC code

CodeForces - 704C的更多相关文章

  1. Codeforces 704C - Black Widow(dp)

    Codeforces 题目传送门 & 洛谷题目传送门 u1s1 感觉这种题被评到 *2900 是因为细节太繁琐了,而不是题目本身的难度,所以我切掉这种题根本不能说明什么-- 首先题目中有一个非 ...

  2. Black Widow CodeForces - 704C (dp)

    大意: 给定一个m个bool变量的方程, 求方程解的个数 给定方程的形式类似于这样 每个括号是一个子式, 每个子式里变量数不超过2, 每个变量出现次数不超过2, 方程右侧一直是1 对每个变量出现的式子 ...

  3. python爬虫学习(5) —— 扒一下codeforces题面

    上一次我们拿学校的URP做了个小小的demo.... 其实我们还可以把每个学生的证件照爬下来做成一个证件照校花校草评比 另外也可以写一个物理实验自动选课... 但是出于多种原因,,还是绕开这些敏感话题 ...

  4. 【Codeforces 738D】Sea Battle(贪心)

    http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1 × n g ...

  5. 【Codeforces 738C】Road to Cinema

    http://codeforces.com/contest/738/problem/C Vasya is currently at a car rental service, and he wants ...

  6. 【Codeforces 738A】Interview with Oleg

    http://codeforces.com/contest/738/problem/A Polycarp has interviewed Oleg and has written the interv ...

  7. CodeForces - 662A Gambling Nim

    http://codeforces.com/problemset/problem/662/A 题目大意: 给定n(n <= 500000)张卡片,每张卡片的两个面都写有数字,每个面都有0.5的概 ...

  8. CodeForces - 274B Zero Tree

    http://codeforces.com/problemset/problem/274/B 题目大意: 给定你一颗树,每个点上有权值. 现在你每次取出这颗树的一颗子树(即点集和边集均是原图的子集的连 ...

  9. CodeForces - 261B Maxim and Restaurant

    http://codeforces.com/problemset/problem/261/B 题目大意:给定n个数a1-an(n<=50,ai<=50),随机打乱后,记Si=a1+a2+a ...

随机推荐

  1. 北京Uber优步司机奖励政策(高峰期5倍奖励)(12月7日)

    用户组:人民优步及电动车(适用于12月7日) 滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http ...

  2. <进阶版>Markdown指南

    有道云笔记内置Markdown编辑器和使用指南. “进阶版”有道云笔记Markdown指南,教你如何进一步掌握待办.清单.流程图和甘特图. 0 待办和清单 待办事项和清单在日常工作.生活中经常被使用. ...

  3. day 6 老王开枪打人

    1.图示 2 程序 1)版本1:框架的搭建 def main(): '''用来控制这个程序的流程''' pass #1.创建alex对象 #2.创建1个枪对象 #3.创建1个弹夹对象 #4.创建子弹对 ...

  4. Java:二进制(原码、反码、补码)与位运算

    一.二进制(原码.反码.补码) 二进制的最高位是符号位(“0”代表正数,“1”代表负数): Java中没有无符号数: 计算机以整数的补码进行运算: 1.  原码:将一个整数转换成二进制表示 以 int ...

  5. ORB-SLAM(五)KeyFrame类-最小生成树

    KeyFrame中维护了一个map,保存了与当前帧共视的KeyFrame*与权重(共视MapPonits数量).对关键帧之间关系是用加权有向图来完成的,那么理解其spanning tree生成树的原理 ...

  6. Python 更换国内pip源

    pip国内的一些镜像: 阿里云 http://mirrors.aliyun.com/pypi/simple/   中国科技大学 https://pypi.mirrors.ustc.edu.cn/sim ...

  7. Python3.5+selenium(11)脚本模块化&参数化

    mail126.py脚本如下 from selenium import webdriver from time import sleep from model1 import Login driver ...

  8. Android 简介

    一 Android起源 android: 机器人 android是google公司开发的基于Linux2.6的免费开源操作系统 2005 Google收购 Android Inc. 开始 Dalvik ...

  9. Unity编辑器 - 自动排版

    Unity编辑器 - 自动排版 使用花括号提高可读性 //一组横向排列的控件 GUILayout.BeginHorizontal(); { GUILayout.BeginVertical(); { / ...

  10. Unity 编辑器扩展

    自定义检视面板的使用: 先是定义一个脚本文件,我们来修饰它的检视面板: [HelpURL("http://www.baidu.com")] public class Atr : M ...