【题目】C. Black Widow

【题意】给定一个表达式,形式为(...)^(...)^......^(...)=1(n个括号),括号中为1~2个值取或。有m个变量,给出表达式的值为xi或 !xi,xi只能为0或1,求变量赋值使得表达式成立的方案数。每个变量至多出现两次。n,m<=10^5。

【算法】动态规划+模拟

【题解】每个括号视为一个点,对于同时出现在两个括号内的变量将两个点连边(边须记两边异同)。由于每个变量至多出现两次,所以一条边就可以代表一个变量。

由于每个括号至多两个变量,所以整个图是若干独立的链或环。

对于链:f[i][j][k]表示考虑到第i条边,当前边取值j=0或1,当前全局取值k=0或1的方案数。

从链的一端开始考虑,到链的另一端结束。

对于环:先决定好第一条边的取值,然后像链一样做即可。

最后将若干子图用简单的DP或组合数计算出最终答案。

复杂度O(n)。

实际操作过程相当复杂,请务必小心食用本题……QAQ

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
using namespace std;
int read(){
char c;int s=,t=;
while(!isdigit(c=getchar()))if(c=='-')t=-;
do{s=s*+c-'';}while(isdigit(c=getchar()));
return s*t;
}
const int maxn=,MOD=1e9+;
int f[maxn][][],dp[][],tot=,first[maxn],in[maxn],ans[maxn][],cnt,fir;
int n,m,c[maxn][],d[maxn][],uv,uuv,vv,be,fr,p[maxn];
bool vis[maxn];
struct edge{int v,w,from;}e[maxn*];
void insert(int u,int v,int w){tot++;e[tot].v=v;e[tot].w=w;e[tot].from=first[u];first[u]=tot;in[v]++;}
int M(int x){return x>=MOD?x-MOD:x;}
void dfs(int x,int fa,int w){
bool ok=;vis[x]=;
f[x][][]=M(f[fa][][w]+f[fa][][w^]);
f[x][][]=M(f[fa][][]+f[fa][][]);
f[x][][]=M(f[fa][][w^]+f[fa][][w]);
f[x][][]=M(f[fa][][]+f[fa][][]);
for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa){
ok=;
dfs(e[i].v,x,e[i].w);
}
if(ok){ ans[cnt][]=M(ans[cnt][]+M(f[x][][]+(p[x]?:f[x][][])));
ans[cnt][]=M(ans[cnt][]+M(f[x][][]+(p[x]?:f[x][][])));
}
}
void round(int x,int fa,int w,int b){
vis[x]=;
f[x][][]=M(f[fa][][w]+f[fa][][w^]);
f[x][][]=M(f[fa][][]+f[fa][][]);
f[x][][]=M(f[fa][][w^]+f[fa][][w]);
f[x][][]=M(f[fa][][]+f[fa][][]);
for(int i=first[x];i;i=e[i].from)if(i!=fr&&(i^)!=b){
if(e[i].v!=be)round(e[i].v,x,e[i].w,i);
else{
if(!fir){
ans[cnt][]=M(f[x][e[i].w^][]+f[x][e[i].w][]);
ans[cnt][]=M(f[x][e[i].w][]+f[x][e[i].w^][]);
}
else{
ans[cnt][]=M(ans[cnt][]+M(f[x][][]+f[x][][]));
ans[cnt][]=M(ans[cnt][]+M(f[x][][]+f[x][][]));
}
}
}
}
int main(){
n=read();m=read();
for(int i=;i<=n;i++){
int k=read();if(k==)p[i]=;
for(int j=;j<=k;j++){
int x=read();
if(x<)c[-x][++c[-x][]]=i,d[-x][c[-x][]]=;
else c[x][++c[x][]]=i;
}
}
for(int i=;i<=m;i++){
if(c[i][]==)uv++;
if(c[i][]==){
if(c[i][]==c[i][]){p[c[i][]]=;if(d[i][]==d[i][])uuv++;else vv++;continue;}
insert(c[i][],c[i][],d[i][]^d[i][]);
insert(c[i][],c[i][],d[i][]^d[i][]);
}
}
for(int i=;i<=n;i++)if(!vis[i]&&in[i]==){
cnt++;
f[][][]=;
dfs(i,,);
if(!p[i]){
dfs(i,,);
}
f[][][]=;
}
for(int i=;i<=n;i++)if(!vis[i]&&in[i]==){
cnt++;
f[i][][]=;fir=;be=i;vis[i]=;fr=e[first[i]].from;
round(e[first[i]].v,i,e[first[i]].w,first[i]);
f[i][][]=;f[i][][]=;fir=;
round(e[first[i]].v,i,e[first[i]].w,first[i]);
}
for(int i=;i<=n;i++)if(!vis[i]&&in[i]==&&p[i]!=){cnt++;ans[cnt][]=;ans[cnt][]=p[i]?:;}
int x=;
dp[x][vv&]=;
for(int i=;i<=vv;i++)dp[x][vv&]=dp[x][vv&]*%MOD;
for(int i=;i<=uuv;i++){
x=-x;
dp[x][]=M(dp[-x][]+dp[-x][]);
dp[x][]=M(dp[-x][]+dp[-x][]);
}
for(int i=;i<=cnt;i++){
x=-x;
dp[x][]=(1ll*ans[i][]*dp[-x][]+1ll*ans[i][]*dp[-x][])%MOD;
dp[x][]=(1ll*ans[i][]*dp[-x][]+1ll*ans[i][]*dp[-x][])%MOD;
}
for(int i=;i<=uv;i++)dp[x][]=dp[x][]*%MOD;
printf("%d",dp[x][]);
return ;
}

【CodeForces】704 C. Black Widow 动态规划+模拟的更多相关文章

  1. codeforces 723B Text Document Analysis(字符串模拟,)

    题目链接:http://codeforces.com/problemset/problem/723/B 题目大意: 输入n,给出n个字符的字符串,字符串由 英文字母(大小写都包括). 下划线'_' . ...

  2. Codeforces Round #304 C(Div. 2)(模拟)

    题目链接: http://codeforces.com/problemset/problem/546/C 题意: 总共有n张牌,1手中有k1张分别为:x1, x2, x3, ..xk1,2手中有k2张 ...

  3. Codeforces 749C:Voting(暴力模拟)

    http://codeforces.com/problemset/problem/749/C 题意:有n个人投票,分为 D 和 R 两派,从1~n的顺序投票,轮到某人投票的时候,他可以将对方的一个人K ...

  4. Educational Codeforces Round 2 A. Extract Numbers 模拟题

    A. Extract Numbers Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/600/pr ...

  5. Codeforces 716B Complete the Word【模拟】 (Codeforces Round #372 (Div. 2))

    B. Complete the Word time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  6. CodeForces 797C Minimal string:贪心+模拟

    题目链接:http://codeforces.com/problemset/problem/797/C 题意: 给你一个非空字符串s,空字符串t和u.有两种操作:(1)把s的首字符取出并添加到t的末尾 ...

  7. Codeforces 37D Lesson Timetable - 组合数学 - 动态规划

    题目传送门 神奇的门I 神奇的门II 题目大意 有$n$组学生要上课2次课,有$m$个教室,编号为$1$到$m$.要确定有多少种不同的安排上课的教室的方案(每组学生都是本质不同的),使得它们满足: 每 ...

  8. Codeforces Beta Round #3 C. Tic-tac-toe 模拟题

    C. Tic-tac-toe 题目连接: http://www.codeforces.com/contest/3/problem/C Description Certainly, everyone i ...

  9. Codeforces Beta Round #1 B. Spreadsheets 模拟

    B. Spreadsheets 题目连接: http://www.codeforces.com/contest/1/problem/B Description In the popular sprea ...

随机推荐

  1. (八)Jmeter怎么通过后置处理器去做关联

     一.Jmeter关联的方式: Jmeter中关联可以在需要获取数据的请求上 右键-->后置处理器 选择需要的关联方式,如下图有很多种方法可以提取动态变化数据: 二.正则表达式提取器: 1.比如 ...

  2. Additinal Dependencies和#pragma comment(lib,"*.lib")的分析

     网上.一些书上也写道,这两种方式作用一样.其实仔细分析,它们两者还是有非常大的差异的. Additinal Dependencies和#pragma comment(lib,"*.lib& ...

  3. [计算机网络-数据链路层] CSMA、CSMA/CA、CSMA/CD详解

    1.CSMA(载波侦听多路访问协议) CSMA 当其他节点检测到信道被占用时不发送数据.但是当数据发送完后其他节点同时检测到信道为空闲,之后又在同一时刻发送数据,可能再次产生冲突. 2.CSMA/CD ...

  4. 【Python】Python对象类型及其运算

    Python对象类型及其运算 基本要点: 程序中储存的所有数据都是对象(可变对象:值可以修改 不可变对象:值不可修改) 每个对象都有一个身份.一个类型.一个值 例: >>> a1 = ...

  5. bzoj1050[HAOI2006]旅行comf(枚举+贪心+并查集)

    Description 给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000).给你两个顶点S和T,求一条路径,使得路径上最大 ...

  6. BZOJ3594 SCOI2014方伯伯的玉米田(动态规划+树状数组)

    可以发现每次都对后缀+1是不会劣的.考虑dp:设f[i][j]为前i个数一共+1了j次时包含第i个数的LIS长度.则f[i][j]=max(f[i][j-1],f[k][l]+1) (k<i,l ...

  7. P3469 [POI2008]BLO-Blockade

    题意翻译 在Byteotia有n个城镇. 一些城镇之间由无向边连接. 在城镇外没有十字路口,尽管可能有桥,隧道或者高架公路(反正不考虑这些).每两个城镇之间至多只有一条直接连接的道路.人们可以从任意一 ...

  8. unity3D AR涂涂乐制作浅谈

    unity3D AR涂涂乐制作浅谈 AR为现在是虚拟现实较为火爆的一个技术,其中有个比较炫酷的就是AR涂涂乐的玩法,这个技术可以把扫描到的图片上的纹理 粘贴到模型上实现为模型上色的功能,但是我们需要怎 ...

  9. Nowcoder 练习赛 23 D Where are you 解题报告

    Where are you 链接: https://ac.nowcoder.com/acm/contest/272/D 来源:牛客网 题目描述 小\(p\)和他的朋友约定好去游乐场游玩,但是他们到了游 ...

  10. Redis的Set无序集合命令

    Set是集合,它是string类型的无序集合.set是通过hash table实现的,添加.删除和查找的复杂度都是0(1).对集合我们可以取并集.交集.差集.通过这些操作我们可以实现sns中的好友推荐 ...