由于每一个运算都有括号,因此添加的运算不会改变运算顺序

先将其建出一棵表达式树,也就是维护两个栈,是节点和运算符优先级单调递增的栈(设置左括号优先级最低,右括号弹出直至左括号)

每一次运算,也就是新建一个节点(节点上记录操作符),并将栈顶的两个节点作为其儿子即可

关于?是操作符还是变量的判定,只需要根据上一个字符是左括号还是右括号即可

建出表达式树后,令$S$是一个$2^{2^{4}}$的二进制数,表示定义$f_{k,S}$表示以$k$为根的子树中,每一种取值的答案为$S$在该位置上的值的方案数,合并根据or或and做卷积,复杂度为$o(Ln2^{n})$($L=|s|$)

  1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 505
4 #define S (1<<16)
5 #define mod 1000000007
6 stack<int>st_op,st_num;
7 int V,n,ans,a[N],ls[N],rs[N],vis[105],f1[S],f2[S],f3[S],g[11][S],f[N][S];
8 char s[N];
9 int turn_num(int k){
10 if (('A'<=s[k])&&(s[k]<='D'))return s[k]-'A';
11 if (('a'<=s[k])&&(s[k]<='d'))return s[k]-'a'+4;
12 if ((s[k]=='?')&&((!k)||(s[k-1]=='(')))return 8;
13 return -1;
14 }
15 void merge(){
16 a[++V]=st_op.top();
17 st_op.pop();
18 rs[V]=st_num.top();
19 st_num.pop();
20 ls[V]=st_num.top();
21 st_num.pop();
22 st_num.push(V);
23 }
24 void FWT_or(int *a,int p){
25 for(int i=0;i<(1<<4);i++)
26 for(int j=0;j<S;j++)
27 if (j&(1<<i))a[j]=((a[j]+p*a[j^(1<<i)])%mod+mod)%mod;
28 }
29 void FWT_and(int *a,int p){
30 for(int i=0;i<(1<<4);i++)
31 for(int j=0;j<S;j++)
32 if (j&(1<<i))a[j^(1<<i)]=((a[j^(1<<i)]+p*a[j])%mod+mod)%mod;
33 }
34 void dfs(int k){
35 if ((!ls[k])&&(!rs[k]))return;
36 dfs(ls[k]);
37 dfs(rs[k]);
38 if (!a[k]){
39 FWT_and(f[ls[k]],1);
40 FWT_and(f[rs[k]],1);
41 for(int i=0;i<S;i++)f[k][i]=1LL*f[ls[k]][i]*f[rs[k]][i]%mod;
42 FWT_and(f[k],-1);
43 }
44 if (a[k]==1){
45 FWT_or(f[ls[k]],1);
46 FWT_or(f[rs[k]],1);
47 for(int i=0;i<S;i++)f[k][i]=1LL*f[ls[k]][i]*f[rs[k]][i]%mod;
48 FWT_or(f[k],-1);
49 }
50 if (a[k]==2){
51 memcpy(f1,f[ls[k]],sizeof(f1));
52 memcpy(f2,f[rs[k]],sizeof(f2));
53 FWT_and(f1,1);
54 FWT_and(f2,1);
55 for(int i=0;i<S;i++)f3[i]=1LL*f1[i]*f2[i]%mod;
56 FWT_and(f3,-1);
57 FWT_or(f[ls[k]],1);
58 FWT_or(f[rs[k]],1);
59 for(int i=0;i<S;i++)f[k][i]=1LL*f[ls[k]][i]*f[rs[k]][i]%mod;
60 FWT_or(f[k],-1);
61 for(int i=0;i<S;i++)f[k][i]=(f[k][i]+f3[i])%mod;
62 }
63 }
64 int main(){
65 scanf("%s",s);
66 n=strlen(s);
67 for(int i=0;i<n;i++){
68 int p=turn_num(i);
69 if (p!=-1){
70 a[++V]=p;
71 st_num.push(V);
72 if ((!st_op.empty())&&(st_op.top()!=-1))merge();
73 }
74 else{
75 if (s[i]=='(')st_op.push(-1);
76 if (s[i]=='&')st_op.push(0);
77 if (s[i]=='|')st_op.push(1);
78 if (s[i]=='?')st_op.push(2);
79 if (s[i]==')'){
80 st_op.pop();
81 if ((!st_op.empty())&&(st_op.top()!=-1))merge();
82 }
83 }
84 }
85 while (!st_op.empty())merge();
86 for(int i=0;i<8;i++){
87 int sta=0;
88 for(int j=0;j<(1<<4);j++)
89 if (((j&(1<<i%4))>0)^(i>=4))sta+=(1<<j);
90 g[i][sta]=1;
91 g[8][sta]++;
92 }
93 for(int i=1;i<=V;i++)
94 if ((!ls[i])&&(!rs[i]))memcpy(f[i],g[a[i]],sizeof(f[i]));
95 dfs(V);
96 memset(vis,-1,sizeof(vis));
97 scanf("%d",&n);
98 for(int i=1;i<=n;i++){
99 int k=0,p;
100 for(int j=0;j<4;j++){
101 scanf("%d",&p);
102 if (p)k+=(1<<j);
103 }
104 scanf("%d",&vis[k]);
105 }
106 for(int i=0;i<S;i++){
107 bool flag=0;
108 for(int j=0;j<(1<<4);j++)
109 if ((vis[j]>=0)&&(((i&(1<<j))>0)!=vis[j])){
110 flag=1;
111 break;
112 }
113 if (!flag)ans=(ans+f[V][i])%mod;
114 }
115 printf("%d",ans);
116 }

[cf582E]Boolean Function的更多相关文章

  1. CF582E Boolean Function(DP,状态压缩,FMT)

    简单题. 我第二道自己做出来的 2900 没毛病,我没切过 2800 的题 lqy:"CF 评分 2800 是中等难度" 我活个啥劲啊 为了方便(同时压缩状态个数),先建出表达式树 ...

  2. 【CF582E】Boolean Function 树形DP+FWT

    [CF582E]Boolean Function 题意:给你一个长度为n的表达式,其中未知数有A,B,C,D和?,运算有&和|和?(表达式中用括号确定了唯一的运算顺序).?代表A,B,C,D或 ...

  3. 快速沃尔什变换&快速莫比乌斯变换小记

    u1s1 距离省选只剩 5 days 了,现在学新算法真的合适吗(( 位运算卷积 众所周知,对于最普通的卷积 \(c_i=\sum\limits_{j+k=i}a_jb_k\),\(a_jb_k\) ...

  4. WC2021 题目清单

    Day2 上午 <IOI题型与趣题分析> 来源 题目 完成情况 备注 IOI2002 Day1T1 Frog 已完成 IOI2002 Day1T2 Utopia IOI2002 Day1T ...

  5. JavaScript中function的多义性

    JavaScript 中的 function 有多重意义.它可能是一个构造器(constructor),承担起对象模板的作用: 可能是对象的方法(method),负责向对象发送消息.还可能是函数,没错 ...

  6. Function对象

    Function对象是js中很重要的一个元素,js中所有自定义的函数都是Function对象,所以String,Number,Boolean,function等都是Function对象.所以,在使用t ...

  7. 从C#到TypeScript - function

    总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...

  8. DiscuzX /source/function/function_core.php通用核心函数库文件分析

    ... <?php /** * [Discuz!] (C)2001-2099 Comsenz Inc. * This is NOT a freeware, use is subject to l ...

  9. JAVA8的java.util.function包 @FunctionalInterface

    1 函数式接口java.util.function https://www.cnblogs.com/CobwebSong/p/9593313.html 2 JAVA8的java.util.functi ...

随机推荐

  1. oracle扩展表空间

    1.  查看表空间的名字及文件所在的位置 select tablespace_name, file_id, file_name, round(bytes / (1024 * 1024), 0) tot ...

  2. C++核心编程 1 程序的内存模型

    1.内存分区模型 C++程序在执行时,将内存大方向划分为4个区域 代码区:存放函数体的二进制代码,由操作系统进行管理(写的所有代码都在代码区) 全局区:存放全局变量.静态变量以及常量 栈   区:由编 ...

  3. 从零入门 Serverless | 课时5 函数的调试与部署

    作者 | 江昱 阿里巴巴高级产品经理 本文整理自<Serverless 技术公开课>,关注"Serverless"公众号,回复"入门",即可获取 S ...

  4. $\Large{\LaTeX}$ 常用公式

    $$\Large{\LaTeX}$$: \[\Large{\LaTeX} \] $ $ 表示行内 $$ $$ 表示独立 $\operatorname{lcm}(x)$\(\operatorname{l ...

  5. 复杂对象List集合的排序

    对于集合的排序,直接的有sort().间接的有借用compareTo.Comparable等,但是对于相对复杂的对象集合,还得自己实现方法来处理. 现在有这样一个思路: 第一步:从需要排序的对象集合中 ...

  6. python os.walk处理树状目录结构的文件

    在项目工作中,时常需要用到处理文件的方法,尤其是在windows环境下的树状目录结构 os.walk恰好能完美的处理这种树状目录结构文件,能高效地帮助我们得到我们需要处理的文件 目录结构: Deskt ...

  7. 单片机零基础学习之从“点灯”入门STM32

    本篇文章通过一个简单的例子来熟悉模块化编程以及利用库函数的方法进行开发使用STM32外设的基本流程. 首先,我们打开本讲的例程,在工程目录我们可以看到驱动分组下有 led.delay 两个.c源文件, ...

  8. STM32 学习笔记之中断应用概览--以f103为例

    异常类型 F103 在内核水平上搭载了一个异常响应系统, 支持为数众多的系统异常和外部中断.其中系统异常有8 个(如果把Reset 和HardFault 也算上的话就是10 个),外部中断有60个.除 ...

  9. Spring:所有依赖项注入的类型

    一.前言 Spring文档严格只定义了两种类型的注入:构造函数注入和setter注入.但是,还有更多的方式来注入依赖项,例如字段注入,查找方法注入.下面主要是讲使用Spring框架时可能发生的类型. ...

  10. sum-root-to-leaf-numbers leetcode C++

    Given a binary tree containing digits from0-9only, each root-to-leaf path could represent a number. ...