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

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

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

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

建出表达式树后,令$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. Lamport时间戳论文笔记

    本文主要参考文献[1]完成. 声明:本人仅在博客园发表了本文章,笔名LightningStar,其他网站均为转载. 笔记 私以为,论文中作者的核心工作是为分布式系统建立了一种数学模型,并基于这种数学模 ...

  2. PostgreSQL 大小写问题 一键修改表名、字段名为小写

    标准的SQL是不区分大小写的.但是PostgreSQL对于数据库中对象的名字允许使用支持大小写区分的定义和引用方法.方式就是在DDL中用双引号把希望支持大小的对象名括起来.比如希望创建一个叫AAA的表 ...

  3. a标签刷新当前页面

    <a href="javascript:location.reload();">刷新页面</a>

  4. Python | JSON 数据解析(Json & JsonPath)

    一.什么是JSON? JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式.它基于 ECMAScript (欧洲计算机协会制定的js规范)的一 ...

  5. css3新增属性-background背景

    css3新增属性 边框属性 背景属性 文字属性 颜色属性 背景属性 属性 说明 background-image 添加背景图片 background-size 指定背景图像的大小 background ...

  6. 洛谷2408不同字串个数/SPOJ 694/705 (后缀数组SA)

    真是一个三倍经验好题啊. 我们来观察这个题目,首先如果直接整体计算,怕是不太好计算. 首先,我们可以将每个子串都看成一个后缀的的前缀.那我们就可以考虑一个一个后缀来计算了. 为了方便起见,我们选择按照 ...

  7. 洛谷3348 大森林 (LCT + 虚点 + 树上差分)

    这可真是道神仙题QWQ问了好多\(dalao\)才稍微明白了一丢丢做法 首先,我们假设不存在\(1\)操作,那么对于询问的一段区间中的所有的树,他们的形态应该是一样的 甚至可以直接理解为\(0\)操作 ...

  8. scratch塔罗牌的制作

    首先,这个程序的流程是洗牌->占卜,很简单的一个程序.那个程序的组成是什么呢? 该程序由22张大卡.开始洗牌按钮.占卜按钮和说出占卜结果的角色组成. 先来说说开始洗牌按钮吧. 开始的时候移动到相 ...

  9. F1英国大奖赛-银石赛道地图及弯道

    背景 今天晚上(2020-08-02)是今年英国大奖赛的正赛.刚好了解了一下赛道地图.记录一下,明年就不用到处找了. 简介 银石赛道(Silverstone Circuit)由一个废弃的空军基地改建, ...

  10. redis中lua脚本的简单使用

    一.背景 在使用redis的过程中,发现有些时候需要原子性去操作redis命令,而redis的lua脚本正好可以实现这一功能.比如: 扣减库存操作.限流操作等等. redis的pipelining虽然 ...