题目大意:给你一个逻辑表达式,然后让你计算表达式为真的取值情况数,表达式由一系列的 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. 【机器学习笔记】循环神经网络RNN

    1. 从一个栗子开始 - Slot Filling 比如在一个订票系统上,我们的输入 "Arrive Taipei on November 2nd" 这样一个序列,我们设置几个槽位 ...

  2. ubuntu网卡

    查看网卡类型  http://blog.csdn.net/eddy_liu/article/details/6578819 qii@ubuntu:~$ lspci | grep -i net 03:0 ...

  3. 创龙DSP6748学习之RS485收发

    1. 先看下原理图,第一个问题,RS485其实就是使用的串口USART1,同时485的输出脚之间接120欧姆的电阻. 遇到个问题,为什么有两个使能引脚?还有RS485_A和RS485_B为什么分别接上 ...

  4. /proc/meminfo详解

    cat /proc/meminfo   读出的内核信息进行解释, 下篇文章会简单对读出该信息的代码进行简单的分析. MemTotal:       507480 kB MemFree:         ...

  5. libevent学习四(Working with events)

    1.事件的分类 文件可写 文件可读 超时发生 信号发生 用户触发事件   2事件的生命周期        --非 persistent                                 ...

  6. c和c++的强制类型转换

    我们知道c语言中的类型转换只有一种, TYPE b = (TYPE)a; 而在c++中按照不同作用的转换类型将其细分为三个显示类型转换符号static_cast, const_cast, reinte ...

  7. VIN码识别,车架号识别,OCR扫描工具

    近年二手车交易市场火爆,对二手车估值需要了详细解二手车的历史状况,车架号(VIN码)是车辆唯一的身份标识,也是了解二手车车况的入口,车商和二手车平台会频繁的进行车况查询,VIN码扫描识别技术给车辆估值 ...

  8. JMeter随机上传附件

    方法一: 1.添加一个前置Beanshell 2.输入代码: File folder = new File("/path/to/your/folder/with/audiofiles&quo ...

  9. TW实习日记:第20-21天

    为什么上周五没写呢,因为上周五一直在熟悉业务流程...根本不会写一些复杂的业务代码,因为没有业务流程图!!!在学校的上需求分析和UML建模课的时候,还有软件工程课的时候,想着这都什么鬼啊,听来干嘛,写 ...

  10. Vue 编程之路(三)—— Vue 中子组件在父组件的 v-for 循环里,父组件如何调取子组件的事件

    (标题的解决方案在第二部分) 最近公司的一个项目中使用 Vue 2.0 + element UI 实现一个后台管理系统的前端部分,属于商城类型. 一.前期思路: 其中在“所有订单”页面,UI 给的设计 ...