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

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

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

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

建出表达式树后,令$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. GDP区域分布图的生成与对比(ArcPy实现)

    一.背景 各地区经济协调发展是保证国民经济健康持续稳定增长的关键.GDP是反映各地区经济发展状况的重要指标.科学准确分析各地区GDP空间分布特征,对制定有效措施,指导经济协调发展具有重要参考价值. 二 ...

  2. 题解 [HAOI2018]反色游戏

    题目传送门 题目大意 给出一个 \(n\) 个点 \(m\) 条无向边的图,每个点都有一个 \(\in [0,1]\) 的权值,每次可以选择一条边,然后将该边相连两点权值异或上 \(1\).问有多少种 ...

  3. 题解 CF1172E Nauuo and ODT

    题目传送门 题目大意 给出一个 \(n\) 个点的树,每个点有颜色,定义 \(\text{dis}(u,v)\) 为两个点之间不同颜色个数,有 \(m\) 次修改,每次将某个点的颜色进行更改,在每次操 ...

  4. vue基本指令与脚手架基本配置

    脚手架(@vue/cli)创建项目启动服务 1.创建项目 vue create 项目名字 2.启动项目 进入项目根目录,运行以下命令 yarn serve 3.脚手架目录代码分析 ├── node_m ...

  5. Noip模拟8 2021.6.17

    T1 星际旅行 仔细一看,发现像一个欧拉路(简称一笔画). 满足"可以一笔画"的条件是: 1.所有点都有偶数条连边; 2.有偶数个点连奇数条边; 满足以上两个条件的任意一个即可一笔 ...

  6. 最小最大堆min-max Heap

    (1)由性质5只能插在奇数层,即根节点处,7下沉到右堆的min level,10下沉到max level,插入后满足min-max heap性质,很容易画出: (2)由性质80也是向右堆插入,且插入到 ...

  7. 常用Java API:大数类

    摘要 java中的基础数据类型能存储的最大的二进制数是 2 ^ 63 - 1, 对应的十进制数是9223372036854775807,也就是说只要运算过程中会超过这个数,就会造成数据溢出,从而造成错 ...

  8. Python课程笔记(九)

    本次课程主要学习了Excel和JSON格式的一些读写操作.课程代码 一.Excel数据读写操作 1.安装模块 pip install xlrd pip install xlwt 网不好可以采用三方库: ...

  9. $time $stime $realtime

    1,$time The $time system function returns an integer that is a 64-bit time, scaled to the timescale ...

  10. path-sum-ii leetcode C++

    Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given su ...