【题目】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. Windows上安装、配置MySQL的常见问题

    一,MySQL的下载安装 MySQL的安装过程就不说了,基本上和一般软件的安装过程没什么两样,就是一路点next,设置的root用户的密码要牢记.具体教程可以参考:http://jingyan.bai ...

  2. 第三章 ServerSpcket用法详解

    构造ServerSocket ServerSocket的构造方法如下: ServerSocket() //Creates an unbound server socket. ServerSocket( ...

  3. php多维数组排序 3

    本文实例讲述了php简单实现多维数组排序的方法.分享给大家供大家参考,具体如下: 之前在做一个功能的时候,必须要把数据放到二维数组里并且排序,然后上网找找解决思路, 这时候会用到array_multi ...

  4. spring mvc $.ajax没有指定contentType ,导致后台无法接收到数据

    var formData = JSON.stringify(this.rows); //将表单中的数据转为字符串 $.ajax({ type: "post", url: 'http ...

  5. 【.Net】win10 uwp unix timestamp 时间戳 转 DateTime

    有时候需要把网络的 unix timestamp 转为 C# 的 DateTime ,在 UWP 可以如何转换? 转换函数可以使用下面的代码 private static DateTime UnixT ...

  6. python的N个小功能(文本字段对应数值,经纬度计算距离,两个时间点计算时间间隔)

    案例1 >>> import pandas as pd >>> df=pd.DataFrame({'A':[1,2,3],'B':[1,2,3],'C':[1,2, ...

  7. Authenticator及AuthenticationStrategy

    Authenticator的职责是验证用户帐号,是Shiro API中身份验证核心的入口点: 如果验证成功,将返回AuthenticationInfo 验证信息:此信息中包含了身份及凭证:如果验证失败 ...

  8. LOJ2430:[POI2014]沙拉餐厅Salad Bar——题解

    https://loj.ac/problem/2430 是的我BZOJ又没卡过……懒得卡了. 参考:https://blog.csdn.net/zqh_wz/article/details/52887 ...

  9. 被动式pocscan扫描神器搭建

    1.搭建环境: 操作系统为:ubuntu16.04 x64位系统,内核版本3.0.10以上 2.安装docker镜像 root@backlion-virtual-machine:/# apt-get ...

  10. bzoj3192: [JLOI2013]删除物品(树状数组)

    既然要从一个堆的堆顶按顺序拿出来放到第二个堆的堆顶,那么我们就可以把两个堆顶怼在一起,这样从一个堆拿到另一个堆只需要移动指针就好了. 换句话说,把1~n倒着,n+1到n+m正着,用一个指针把两个序列分 ...