Proposition
提供 \(k\) 个变量 \((k\leq 4)\) 可独立取值为 \(0,1\),两种运算分别等价于 \(\neg a\) 和 \(\neg a \lor b\) 。
你需要恰好使用 \(n\) 个运算符构造一个公式 \(Q\) ,一共 \(m\) 组询问 \((m\leq 500)\),每次寻味有给定一个恰好含有一个 \(Q\) 的公式 \(P\ (|P|\leq 4000)\) ,求有多少种合法的 \(Q\) 使得无论 \(k\) 个变量取何值,\(P\) 的值总为真。
考虑对于 \(k\) 个变量一共有 \(2^k\) 种可能的取值。假设 \(Q\) 已经构造完毕, \(Q\) 在 \(2^k\) 种变量取值可能中分别对应 \(2^k\) 个\(0,1\),将这 \(2^k\) 个 \(0,1\) 压成一个 \(2^k\) 位的状态,那么一个 \(Q\) 对应着 \(2^{2^k}\) 种状态之一,那么设 \(F_{i,sta}\) 为用 \(i\) 个符号状态为 \(sta\) 的 \(Q\) 的数量。
\]
然后对于一个 \(P\) 暴力枚举 \(k\) 个变量的 \(2^k\) 种取值和 \(Q\) 的取值 \((0,1)\) 代入算一遍判断是否合法,这样就得到了对于 \(2^k\) 种变量的取值 \(Q\) 的限制 \(0\) 或 \(1\) 或 都可以。 那么再枚举 \(F\) 所对应的 \(2^{2^k}\) 种取值,将合法的取值加起来即可。
这样单次询问的复杂度为优秀的 \(O(2^{k+1}|P|+2^{2^k})\) ,此时复杂度瓶颈在于朴素 \(DP\) 预处理的 \(O(n^2\times 2^{2^{k+1}})\)
由于\(sta=\neg s_1\lor s_2\),\(i=j+k\),所以可以直接以 \(sta\) 为下标做 \(FWT\) 或卷积,并用 \(i\) 为下标做个背包,可以做到 \(O(n^2\times 2^k\times 2^{2^k})\)。
所以最终复杂度为\(O(n^2\times 2^k\times 2^{2^k}+m\times(2^{k+1}|P|+2^{2^k}))\)。
#include<bits/stdc++.h>
#define LL long long
#define M 65560
using namespace std;
int read(){
int nm=0,fh=1; char cw=getchar();
for(;!isdigit(cw);cw=getchar()) if(cw=='-') fh=-fh;
for(;isdigit(cw);cw=getchar()) nm=nm*10+(cw-'0');
return nm*fh;
}
#define mod 1000000007
#define add(a,b) (((a)+(b))>=mod?((a)+(b)-mod):((a)+(b)))
#define mns(a,b) (((a)-(b))<0?((a)-(b)+mod):((a)-(b)))
#define mul(a,b) ((LL)(a)*(LL)(b)%mod)
void upd(int &x,int y){x=add(x,y);}
int n,m,len,F[72][M],G[72][M],maxn,LEN,S[M],top,st[M],tp,b[2]; char ch[4002];
void FWT(int *x,int kd){
for(int tt=1;tt<len;tt<<=1) for(int st=0;st<len;st+=(tt<<1)) for(int pos=st;pos<st+tt;pos++)
x[pos+tt]=((kd>0)?add(x[pos+tt],x[pos]):mns(x[pos+tt],x[pos]));
}
int op(int x,int y,int kd){return (kd==-3)?((!x)|y):(!y);}
int calc(int STA,int KD){
for(int i=1;i<=top;i++){
if(S[i]<-2) st[tp-1]=op(st[tp-1],st[tp],S[i]),tp--;
else if(S[i]==10) st[++tp]=KD; else if(S[i]==-2) st[++tp]=-2;
else st[++tp]=((STA>>S[i])&1);
} return st[(tp=0)+1];
}
bool IN(int x,int tot){return (x&tot)==x;}
int solve(){
scanf("%s",ch),LEN=strlen(ch),top=tp=0; int res=0;
for(int i=0;i<LEN;i++){
if(ch[i]=='(') st[++tp]=-1;
if(ch[i]=='x') S[++top]=ch[++i]-'1'; if(ch[i]=='Q'){S[++top]=10;}
if(ch[i]=='-'){for(i++;tp&&st[tp]<=-3;S[++top]=st[tp--]);st[++tp]=-3;}
if(ch[i]=='~'){S[++top]=-2; while(tp&&st[tp]<=-4) S[++top]=st[tp--];st[++tp]=-4;}
if(ch[i]==')'){while(tp&&st[tp]<=-3) S[++top]=st[tp--];tp--;}
} while(tp) S[++top]=st[tp--]; b[0]=b[1]=0;
for(int i=0;i<maxn;i++) for(int kd=0;kd<2;kd++) b[kd]|=(calc(i,kd)<<i);
for(int i=0;i<len;i++) if(IN(i,b[1])&&IN((len-1)^i,b[0])) upd(res,F[n][i]); return res;
}
int main(){
n=read(),m=read(),len=(1<<(maxn=(1<<m)));
for(int i=0,sta=0;i<m;i++,sta=0){
for(int now=0;now<maxn;now++) if((now>>i)&1) sta|=(1<<now); F[0][sta]++;
}
for(int i=0;i<len;i++) G[0][i]=F[0][(len-1)^i]; FWT(G[0],1),FWT(F[0],1);
for(int i=1;i<=n;i++){
memcpy(F[i],G[i-1],sizeof(F[i]));
for(int k=0;k<i;k++) for(int pos=0;pos<len;pos++)
upd(F[i][pos],mul(G[k][pos],F[i-k-1][pos]));
FWT(F[i],-1),memcpy(G[i],F[i],sizeof(G[i])),reverse(G[i],G[i]+len);
if(i<n) FWT(F[i],1),FWT(G[i],1);
}
for(int T=read();T;--T) printf("%d\n",solve()); return 0;
}
Proposition的更多相关文章
- HDU 5420 Victor and Proposition
Victor and Proposition Time Limit: 6000ms Memory Limit: 524288KB This problem will be judged on HDU. ...
- Theorem、Proposition、Lemma和Corollary等的解释与区别
Theorem:定理.是文章中重要的数学化的论述,一般有严格的数学证明. Proposition:可以翻译为命题,经过证明且interesting,但没有Theorem重要,比较常用. Lemma:一 ...
- Life Is A Funny Proposition After All
你们有没有坐下思考,感到疑惑 ,静静思考,我们为什么在这里 ,生活为什么如此这般 这个问题让无数聪明人喝酒买醉,这是最最奇怪的事情,他们都想弄清楚,科学家们可以展示上千种不同的理论,但从未证明这是为什 ...
- BizDevOps — the true value proposition of workflow engines
转自:https://blog.bernd-ruecker.com/bizdevops-the-true-value-proposition-of-workflow-engines-f342509ba ...
- HDU5420 : Victor and Proposition
以深度建立线段树,线段树父亲节点向儿子节点连边,然后用线段树合并可以得到任何一个点子树的线段树,只需向对应节点的线段树中的$O(\log n)$个点连边即可.为了保证连边关系不发生混乱,线段树需要进行 ...
- <Sicily>Pythagorean Proposition
一.题目描述 One day, WXYZ got a wooden stick, he wanted to split it into three sticks and make a right-an ...
- Java资源大全中文版(Awesome最新版)
Awesome系列的Java资源整理.awesome-java 就是akullpp发起维护的Java资源列表,内容包括:构建工具.数据库.框架.模板.安全.代码分析.日志.第三方库.书籍.Java 站 ...
- 我的LaTeX中文文档模板
中文LaTeX处理模板 环境MiTex内核 编辑环境WinEdit 源码如下: \documentclass[a4paper,12pt]{article} \usepackage{CJK} %设定字号 ...
- Introduction to Microsoft Dynamics 365 licensing
Microsoft Dynamics 365 will be released on November 1. In preparation for that, Scott Guthrie hosted ...
随机推荐
- POJ 2516 Minimum Cost (KM最优匹配)
题意:有N家家店,每家店都对K种货物有需求:同时有M家仓库,对K钟货物有供应.对于每种货物,每个仓库送至每家店都有自己的单位费用.求满足所有店所有货物的最小费用 分析:对于每一种货物,如果总需求大于总 ...
- Loadrunder场景设计篇——IP欺骗
适用协议 LoadRunner的多ip功能允许运行在单一负载生成器上的Vuser可以通过多ip被识别.服务器和路由识别这些vuser为来自不同负载生成器上. 2 在负载生成器(load gene ...
- Loadrunner场景设计篇——负载生成器
1 简介 当执行一个场景时,Controller把场景中的每个用户配到负载生成器(Load generator). 所谓的负载生成器(Load Generator)就是执行Vuser脚本,运行Vus ...
- LeetCode 1. Two Sum 找到两数字求和索引集合
https://leetcode.com/problems/two-sum/description/ 第一种方法 遍历查找 // // main.m // HFCDemo // // Created ...
- git-bash使用ctrl C无法终止nodemon的执行
原因: git的bug 解决:git版本降级为2.10.0好了
- JavaScript中堆栈解析,已经与delete之间的关系。
1,在栈中的数据不会随意删除. 2,堆中的数据可以随意删除. 注意:用eval("var a")定义的变量存放在栈中. var 和function 语句在JavaScript中的优 ...
- jQuery单选框跟复选框美化
在线演示 本地下载
- poj2431 一直Wa
在遍历加油站的时候,会将经过的x加油站放入优先队列,之后将x从数组中删掉,即用最后一个加油站来替代x:这时如果不 “i--”,则会漏掉检查原来的stop[n-1],则可能造成错误. if(stop[i ...
- React Native 常用学习链接地址
Android Studio下载http://www.android-studio.org/ 第二章:Android Studio概述(一)http://ask.android-studio.org/ ...
- React Native导航器之react-navigation使用
在上一节Navigation组件,我们使用系统提供的导航组件做了一个跳转的例子,不过其实战能力不强,这里推荐一个超牛逼的第三方库:react-navigation.在讲react-navigation ...