CF582E Boolean Function(DP,状态压缩,FMT)
简单题。
我第二道自己做出来的 2900
没毛病,我没切过 2800 的题
lqy:“CF 评分 2800 是中等难度”
我活个啥劲啊
为了方便(同时压缩状态个数),先建出表达式树,然后一棵子树就代表一个完整的表达式(要么是单个变量,要么是被一堆匹配的括号恰好包住的)。
注意:(在我的写法里面)叶子都是变量,非叶子都是运算符,每个非叶子有恰好两个儿子,就表示这个运算符把整个表达式分成了哪两个,
然后就开始 DP 了。
明显状压吧?首先四个变量的取值可以压成一个四位二进制数(\(0\) 到 \(15\))。然后再状压一次,压成一个 \(16\) 位二进制数,第 \(i\) 位表示四个变量取值情况是 \(i\) 时表达式的值。
\(dp[u][i]\) 就表示 \(u\) 为根的子树,然后)&@!$^(&*!@#为 \(i\) 的方案数。
暴力转移是 \(O(|s|4^{16})\),不太行。
发现转移是个与卷积和或卷积的形式,FMT 优化。
时间复杂度是 \(O(|s|\times 16\times 2^{16})\),虽然看起来不太稳但是跑得飞快(400ms)……
#include<bits/stdc++.h>
using namespace std;
const int maxn=5555,mod=1000000007,lim=65536;
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
int x=0,f=0;char ch=getchar();
while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return f?-x:x;
}
int n,dp[255][lim],m,a[16],b[16],with[maxn],stk[maxn],tp,cnt,ch[maxn][2],fa[maxn],id[maxn],rt,p[lim],q[lim];
char s[maxn],val[maxn];
bool op[maxn];
void FMT_pre(int *A){
for(int i=1;i<lim;i<<=1)
for(int j=0;j<lim;j+=i<<1)
FOR(k,0,i-1) A[j+k]=(A[j+k]+A[i+j+k])%mod;
}
void IFMT_pre(int *A){
for(int i=1;i<lim;i<<=1)
for(int j=0;j<lim;j+=i<<1)
FOR(k,0,i-1) A[j+k]=(A[j+k]-A[i+j+k]+mod)%mod;
}
void FMT_suf(int *A){
for(int i=1;i<lim;i<<=1)
for(int j=0;j<lim;j+=i<<1)
FOR(k,0,i-1) A[i+j+k]=(A[i+j+k]+A[j+k])%mod;
}
void IFMT_suf(int *A){
for(int i=1;i<lim;i<<=1)
for(int j=0;j<lim;j+=i<<1)
FOR(k,0,i-1) A[i+j+k]=(A[i+j+k]-A[j+k]+mod)%mod;
}
void dfs(int now){
if(ch[now][0]) dfs(ch[now][0]);
if(ch[now][1]) dfs(ch[now][1]);
if(!op[now]){
switch(val[now]){
case 'A':dp[now][65280]=1;break;
case 'B':dp[now][61680]=1;break;
case 'C':dp[now][52428]=1;break;
case 'D':dp[now][43690]=1;break;
case 'a':dp[now][255]=1;break;
case 'b':dp[now][3855]=1;break;
case 'c':dp[now][13107]=1;break;
case 'd':dp[now][21845]=1;break;
case '?':
dp[now][65280]=dp[now][61680]=dp[now][52428]=dp[now][43690]=
dp[now][255]=dp[now][3855]=dp[now][13107]=dp[now][21845]=1;
}
}
else{
if(val[now]!='|'){
FOR(i,0,lim-1) p[i]=dp[ch[now][0]][i],q[i]=dp[ch[now][1]][i];
FMT_pre(p);FMT_pre(q);
FOR(i,0,lim-1) p[i]=1ll*p[i]*q[i]%mod;
IFMT_pre(p);
FOR(i,0,lim-1) dp[now][i]=(dp[now][i]+p[i])%mod;
}
if(val[now]!='&'){
FOR(i,0,lim-1) p[i]=dp[ch[now][0]][i],q[i]=dp[ch[now][1]][i];
FMT_suf(p);FMT_suf(q);
FOR(i,0,lim-1) p[i]=1ll*p[i]*q[i]%mod;
IFMT_suf(p);
FOR(i,0,lim-1) dp[now][i]=(dp[now][i]+p[i])%mod;
}
}
}
int main(){
scanf("%s",s+1);
n=strlen(s+1);
m=read();
FOR(i,0,m-1){
FOR(j,0,3) a[i]=2*a[i]+read();
b[i]=read();
}
FOR(i,1,n){
if(s[i]=='(') stk[++tp]=i;
else if(s[i]==')') with[i]=stk[tp],with[stk[tp]]=i,tp--;
}
FOR(i,1,n) if(s[i]!='(' && s[i]!=')'){
id[i]=++cnt;
val[cnt]=s[i];
int j=i;
while(j<=n && (s[j]!=')' || with[j]>i)) j++;
id[j]=id[with[j]]=cnt;
}
FOR(i,1,n) if(s[i]!='(' && s[i]!=')'){
if(s[i-1]==')' && s[i+1]=='('){
fa[id[i-1]]=fa[id[i+1]]=id[i];
ch[id[i]][0]=id[i-1];
ch[id[i]][1]=id[i+1];
op[id[i]]=1;
}
}
FOR(i,1,cnt) if(!fa[i]) assert(!rt),rt=i;
dfs(rt);
int ans=0;
FOR(i,0,lim-1){
bool flag=true;
FOR(j,0,m-1) if(((i>>a[j])&1)!=b[j]) flag=false;
if(flag) ans=(ans+dp[rt][i])%mod;
}
printf("%d\n",ans);
}
CF582E Boolean Function(DP,状态压缩,FMT)的更多相关文章
- HDU 4336 Card Collector (期望DP+状态压缩 或者 状态压缩+容斥)
题意:有N(1<=N<=20)张卡片,每包中含有这些卡片的概率,每包至多一张卡片,可能没有卡片.求需要买多少包才能拿到所以的N张卡片,求次数的期望. 析:期望DP,是很容易看出来的,然后由 ...
- HDU 1074 Doing Homework (dp+状态压缩)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1074 题目大意:学生要完成各科作业, 给出各科老师给出交作业的期限和学生完成该科所需时间, 如果逾期一 ...
- hdu_4352_XHXJ's LIS(数位DP+状态压缩)
题目连接:hdu_4352_XHXJ's LIS 题意:这题花大篇篇幅来介绍电子科大的一个传奇学姐,最后几句话才是题意,这题意思就是给你一个LL范围内的区间,问你在这个区间内最长递增子序列长度恰为K的 ...
- hdu 4352 数位dp + 状态压缩
XHXJ's LIS Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- 【bzoj1076】[SCOI2008]奖励关 期望dp+状态压缩dp
题目描述 你正在玩你最喜欢的电子游戏,并且刚刚进入一个奖励关.在这个奖励关里,系统将依次随机抛出k次宝物,每次你都可以选择吃或者不吃(必须在抛出下一个宝物之前做出选择,且现在决定不吃的宝物以后也不能再 ...
- hdu4336 Card Collector(概率DP,状态压缩)
In your childhood, do you crazy for collecting the beautiful cards in the snacks? They said that, fo ...
- dp状态压缩
dp状态压缩 动态规划本来就很抽象,状态的设定和状态的转移都不好把握,而状态压缩的动态规划解决的就是那种状态很多,不容易用一般的方法表示的动态规划问题,这个就更加的难于把握了.难点在于以下几个方面:状 ...
- 洛谷 1052 dp 状态压缩
洛谷1052 dp 状态压缩 传送门 (https://www.luogu.org/problem/show?pid=1052#sub) 做完这道题之后,感觉涨了好多见识,以前做的好多状压题目都是将一 ...
- NOIP2005过河[DP 状态压缩]
题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数 ...
- ACM: HDU 5418 Victor and World - Floyd算法+dp状态压缩
HDU 5418 Victor and World Time Limit:2000MS Memory Limit:131072KB 64bit IO Format:%I64d & ...
随机推荐
- QGIS练手 - 数据
又熬夜了... 这篇博客可能会将QGIS数据管理部分和ArcGIS数据管理进行对比学习. 1. 本地数据文件与数据库(矢量) 1.1 文件 QGIS用的是shp文件.kml文件.geojson文件较多 ...
- Linux系统学习 十八、VSFTP服务—虚拟用户访问—配置虚拟用户访问
配置虚拟用户访问 首先至少要关闭userlist 改完配置文件是要重启服务来使它生效 其实在刚装好vsftp的时候的配置文件不用修改的情况下配置虚拟用户访问控制是最好的 local_root选项不影响 ...
- 「Shimo使用指南」mac支持pptp协议的小软件
Mac的好多小伙伴在访问网络设备时觉得远程连接不方便,例如ssh,***登陆都不是很方便,后来又安装了open*** forMac.ISSH等客户端,使用后发现不是很稳定,断线后很久都无法连接等缺点, ...
- ubuntu18.04因java路径原因启动jenkins失败
我的云服务器ubuntu18.04上本来装了jenkins,今天安装完tomcat后,将原有的openjdk卸载了,安装了jdk8u192, 此时浏览器访问8080端口显示的就是tomcat安装成功的 ...
- Java死锁演示
Java死锁演示 在线程中嵌套获取锁导致死锁.思路,尽量不要嵌套获取锁. package com.mozq.demo.demo; public class DeadLockDemo { private ...
- python-paramiko对远程服务器终端的操作
1.with open写文件到本地 2.paramiko SFTPClient将文件推到salt服务端 3.paramiko SSHClient通过salt-cp将文件分发给目标服务器 1. with ...
- NLP入门(九)词义消岐(WSD)的简介与实现
词义消岐简介 词义消岐,英文名称为Word Sense Disambiguation,英语缩写为WSD,是自然语言处理(NLP)中一个非常有趣的基本任务. 那么,什么是词义消岐呢?通常,在我们 ...
- 【朝花夕拾】Android自定义View篇之(三)Canvas绘制文字
前言 转载请声明,转自[https://www.cnblogs.com/andy-songwei/p/10968358.html],谢谢! 前面的文章中在介绍Canvas的时候,提到过后续单独讲Can ...
- C#深入浅出之数据类型
基本数据类型 C#支持完整的BCL(基类库)名字,但是最好都统一使用关键字进行使用与开发,比如使用int而不是System.Int32,以及使用string类型时候应当使用string而 ...
- 关于kubernetes我们还有什么可做的?
kubernetes在容器编排大战中由于应用的可移植性以及支持混合云/多云部署方式上的灵活性.加上开放可扩展的理念,使得周边社区非常活跃.从既有调研结果看,kubernetes已成为容器编排领域的标准 ...