【CodeForces】704 C. Black Widow 动态规划+模拟
【题目】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 动态规划+模拟的更多相关文章
- codeforces 723B Text Document Analysis(字符串模拟,)
题目链接:http://codeforces.com/problemset/problem/723/B 题目大意: 输入n,给出n个字符的字符串,字符串由 英文字母(大小写都包括). 下划线'_' . ...
- Codeforces Round #304 C(Div. 2)(模拟)
题目链接: http://codeforces.com/problemset/problem/546/C 题意: 总共有n张牌,1手中有k1张分别为:x1, x2, x3, ..xk1,2手中有k2张 ...
- Codeforces 749C:Voting(暴力模拟)
http://codeforces.com/problemset/problem/749/C 题意:有n个人投票,分为 D 和 R 两派,从1~n的顺序投票,轮到某人投票的时候,他可以将对方的一个人K ...
- Educational Codeforces Round 2 A. Extract Numbers 模拟题
A. Extract Numbers Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/600/pr ...
- 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 ...
- CodeForces 797C Minimal string:贪心+模拟
题目链接:http://codeforces.com/problemset/problem/797/C 题意: 给你一个非空字符串s,空字符串t和u.有两种操作:(1)把s的首字符取出并添加到t的末尾 ...
- Codeforces 37D Lesson Timetable - 组合数学 - 动态规划
题目传送门 神奇的门I 神奇的门II 题目大意 有$n$组学生要上课2次课,有$m$个教室,编号为$1$到$m$.要确定有多少种不同的安排上课的教室的方案(每组学生都是本质不同的),使得它们满足: 每 ...
- Codeforces Beta Round #3 C. Tic-tac-toe 模拟题
C. Tic-tac-toe 题目连接: http://www.codeforces.com/contest/3/problem/C Description Certainly, everyone i ...
- Codeforces Beta Round #1 B. Spreadsheets 模拟
B. Spreadsheets 题目连接: http://www.codeforces.com/contest/1/problem/B Description In the popular sprea ...
随机推荐
- eclipse生成jar包 注意事项!
原文转自:http://www.cnblogs.com/zhangfei/archive/2013/01/22/2871075.html 第一:普通类导出jar包,我说的普通类就是指此类包含main方 ...
- 从理论到实践,全方位认识DNS
从理论到实践,全方位认识DNS 2015-11-23 程序员之家 作者:selfboot 原文:http://segmentfault.com/a/1190000003956853 对于 DNS(Do ...
- 微信小程序组件 360
data: { nums: 1, start: '', // change:'' // 上一部记忆数据 mid: '' }, mytouchmove: function (e) { var start ...
- java 两个数组合并
需求:两个字符串合并(如果想去重复,参考下一篇--数组去重复及记录重复个数) //方法一 Arrays类 String[] a = {"A","B"," ...
- linux安装py3.6
随手记录: https://www.python.org/ftp/python/3.6.8/Python-3.6.8rc1.tgz 所有linux版本: https://www.python.org/ ...
- HDU4045_Machine scheduling
题意为要你从编号为1-n的所有机器中间选择出r个机器且每一个机器的编号只差不小于k-1,然后将选择的r个机器分为m组有多少种方案. 其实这题目的两个步骤是相互独立的. 总共的方案数等于选择的方案数乘以 ...
- 【转载】Java中的锁机制 synchronized & 偏向锁 & 轻量级锁 & 重量级锁 & 各自优缺点及场景 & AtomicReference
参考文章: http://blog.csdn.net/chen77716/article/details/6618779 目前在Java中存在两种锁机制:synchronized和Lock,Lock接 ...
- 学习Python最好的方法就是实践和教程并行,以下有一些资源和教程,还有一些学习思维导图:
1.Python 的 14 张思维导图下载地址: https://woaielf.github.io/2017/06/13/python3-all/ 2.Python基础教程|菜鸟教程: http:/ ...
- python 内存问题(glibc库的malloc相关)
题记: 这是工作以来困扰我最久的问题.python 进程内存占用问题. 经过长时间断断续续的研究,终于有了一些结果. 项目(IM服务器)中是以C做底层驱动python代码,主要是用C完成 网络交互部分 ...
- TCP/IP协议详解---概述
工作之后,才发现以前在学校里学的东西忘得太快太干净了,现在需要一点点地捡起来了,要不然写几行程序会闹很多笑话会出现很多bug的.从今天开始,翻一翻<TCP/IP协议详解 卷1>这本 ...