提供 \(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. SVN插件下载地址及更新地址

    SVN插件下载地址及更新地址,你根据需要选择你需要的版本.现在最新是1.8.xLinks for 1.8.x Release:Eclipse update site URL: http://subcl ...

  2. MapReduce概述

    MapReduce 源自于Google的MapReduce论文,Hadoop MapReduce是Google MapReduce克隆版 MapReduce适合PB级以上海量数据的离线处理 MapRe ...

  3. 轮询、长轮询、长连接、socket连接、WebSocket

    轮询:客户端定时向服务器发送Ajax请求,服务器接到请求后马上返回响应信息并关闭连接. 优点:后端程序编写比较容易. 缺点:请求中有大半是无用,浪费带宽和服务器资源.(而每一次的 HTTP 请求和应答 ...

  4. 深入理解JVM 垃圾收集器(下)G1收集器

    1.回顾CMS 1.1堆内存结构 1.2新生代GC 1.3老年代GC 2.G1收集器 2.1G1实现概览及使用场景 G1的推荐使用场景 2.2GC 2.2.1新生代GC 2.2.2老年代GC 老年代G ...

  5. Mysql 基本用法

    Java中两种常用的数据库: MYSQL     Oracle MYSQL  :开源免费的数据库,小型的数据库.由瑞典MySQL AB 公司开发,适合中小企业使用,由C语言和C++编写的.已经被Ora ...

  6. PHP设计模式(一):简单工厂模式

  7. LINUX系统运行查看

    1.查看内存使用情况 free -m 2.查看内存,cpu等使用情况排序,使用ps -aux命令 ps -aux --sort=+rss :按内存升序排列 ps -aux --sort=-rss :按 ...

  8. 关于阿里云Symantec免费DV证书部署HTTPS

    获取阿里云Symantec免费DV证书: 官方文件说明: 证书文件214188487290026.pem,包含两段内容,请不要删除任何一段内容. 如果是证书系统创建的CSR,还包含:证书私钥文件214 ...

  9. spring通知的注解

    1.代理类接口Person.java package com.xiaostudy; /** * @desc 被代理类接口 * * @author xiaostudy * */ public inter ...

  10. 使用nagios检测windows服务器

    1.安装nagios windows客户端 下载NSClient++的安装包,注意根据实际的32/64CPU来下载 下载地址 http://sourceforge.net/projects/nscpl ...