提供 \(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\) 的数量。

\[F_{i,sta}=F_{i-1,\neg sta}+\sum\limits_{j+k=i-1,\neg s_1\lor s_2=sta} F_{j,s_1}\times F_{k,s_2}
\]

然后对于一个 \(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的更多相关文章

  1. HDU 5420 Victor and Proposition

    Victor and Proposition Time Limit: 6000ms Memory Limit: 524288KB This problem will be judged on HDU. ...

  2. Theorem、Proposition、Lemma和Corollary等的解释与区别

    Theorem:定理.是文章中重要的数学化的论述,一般有严格的数学证明. Proposition:可以翻译为命题,经过证明且interesting,但没有Theorem重要,比较常用. Lemma:一 ...

  3. Life Is A Funny Proposition After All

    你们有没有坐下思考,感到疑惑 ,静静思考,我们为什么在这里 ,生活为什么如此这般 这个问题让无数聪明人喝酒买醉,这是最最奇怪的事情,他们都想弄清楚,科学家们可以展示上千种不同的理论,但从未证明这是为什 ...

  4. BizDevOps — the true value proposition of workflow engines

    转自:https://blog.bernd-ruecker.com/bizdevops-the-true-value-proposition-of-workflow-engines-f342509ba ...

  5. HDU5420 : Victor and Proposition

    以深度建立线段树,线段树父亲节点向儿子节点连边,然后用线段树合并可以得到任何一个点子树的线段树,只需向对应节点的线段树中的$O(\log n)$个点连边即可.为了保证连边关系不发生混乱,线段树需要进行 ...

  6. <Sicily>Pythagorean Proposition

    一.题目描述 One day, WXYZ got a wooden stick, he wanted to split it into three sticks and make a right-an ...

  7. Java资源大全中文版(Awesome最新版)

    Awesome系列的Java资源整理.awesome-java 就是akullpp发起维护的Java资源列表,内容包括:构建工具.数据库.框架.模板.安全.代码分析.日志.第三方库.书籍.Java 站 ...

  8. 我的LaTeX中文文档模板

    中文LaTeX处理模板 环境MiTex内核 编辑环境WinEdit 源码如下: \documentclass[a4paper,12pt]{article} \usepackage{CJK} %设定字号 ...

  9. Introduction to Microsoft Dynamics 365 licensing

    Microsoft Dynamics 365 will be released on November 1. In preparation for that, Scott Guthrie hosted ...

随机推荐

  1. POJ 2516 Minimum Cost (KM最优匹配)

    题意:有N家家店,每家店都对K种货物有需求:同时有M家仓库,对K钟货物有供应.对于每种货物,每个仓库送至每家店都有自己的单位费用.求满足所有店所有货物的最小费用 分析:对于每一种货物,如果总需求大于总 ...

  2. Loadrunder场景设计篇——IP欺骗

    适用协议 LoadRunner的多ip功能允许运行在单一负载生成器上的Vuser可以通过多ip被识别.服务器和路由识别这些vuser为来自不同负载生成器上.   2  在负载生成器(load gene ...

  3. Loadrunner场景设计篇——负载生成器

    1  简介 当执行一个场景时,Controller把场景中的每个用户配到负载生成器(Load generator). 所谓的负载生成器(Load Generator)就是执行Vuser脚本,运行Vus ...

  4. LeetCode 1. Two Sum 找到两数字求和索引集合

    https://leetcode.com/problems/two-sum/description/ 第一种方法  遍历查找 // // main.m // HFCDemo // // Created ...

  5. git-bash使用ctrl C无法终止nodemon的执行

    原因: git的bug 解决:git版本降级为2.10.0好了

  6. JavaScript中堆栈解析,已经与delete之间的关系。

    1,在栈中的数据不会随意删除. 2,堆中的数据可以随意删除. 注意:用eval("var a")定义的变量存放在栈中. var 和function 语句在JavaScript中的优 ...

  7. jQuery单选框跟复选框美化

    在线演示 本地下载

  8. poj2431 一直Wa

    在遍历加油站的时候,会将经过的x加油站放入优先队列,之后将x从数组中删掉,即用最后一个加油站来替代x:这时如果不 “i--”,则会漏掉检查原来的stop[n-1],则可能造成错误. if(stop[i ...

  9. React Native 常用学习链接地址

    Android Studio下载http://www.android-studio.org/ 第二章:Android Studio概述(一)http://ask.android-studio.org/ ...

  10. React Native导航器之react-navigation使用

    在上一节Navigation组件,我们使用系统提供的导航组件做了一个跳转的例子,不过其实战能力不强,这里推荐一个超牛逼的第三方库:react-navigation.在讲react-navigation ...