题意:
给定函数f(A,B,C,D),其中A,B,C,D∈{0,1),然后a = A^1,b = B^1,c = C^1,d = D^1
题目给出函数的表达式,,很多很多的(x) op (y)形式,()内为变量或嵌套表达式,op为逻辑运算符&或|
其中,(?)代表这个变量由你决定,若op == '?',那么这个表达式由你决定
下面给出m条限制,每条为f(ai,bi,ci,di) = ei的形式
问在给定限制下,有多少可行的方案,使得将f(A,B,C,D)补全后满足所有限制???
solution:
这根本想不出来啊。。。。。。。。。
首先建立出一棵表达式树,方法是每次选择当前剩余表达式中最后一个运算符为树根,然后分成左右两半
最后,,,叶子节点为变量
A,B,C,D的取值情况一共有2^4种,每种情况f(A,B,C,D)都有一个值
定义f[i][mask]为以i为根的子树中的方案数
其中,,,对于mask
不是一共有2^4种ABCD的取值嘛,,这就变成一个2^4位的二进制数码,其中每一位的值对应A,B,C,D选取当前方案时,f(A,B,C,D)的值,此时的方案数(这句话题解里相当难翻译。。。。日)
对于叶子节点,暴力地枚举mask,然后暴力地判断当前点填A,B,C,D,a,b,c,d中哪些能够满足全部16个限制
如果当前节点在表达式中已经确定,暴力判断能否满足即可
对于非叶子节点,逻辑运算符无非是&|两种
f[maski&maskj] += f[lc][maski]*f[rc][maskj]
这是对于&运算的,显然转移方程可以这样写
暴力转移的话,每个mask要枚举其所有子集然后瞎搞,大概要O(2^32)
不过,转移是逻辑运算卷积的形式,,,上FWT即可。。。
其实本题题意和题解还是要靠自己理解的。。。。语言无法表达清楚
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 555;
const int T = 16;
const int maxm = 1<<T;
const string S = "ABCDabcd?";
const int mo = 1000000007;
int ans,f[maxn][maxm],g[maxm];
int n,m,cnt = 1,typ[maxn],lc[maxn],rc[maxn],Mark[maxm],va[8],ti[8];
char s[maxn];
void Build(int now,int l,int r)
{
if (l == r) {
for (int i = 0; i < 9; i++)
if (S[i] == s[l]) {typ[now] = i; return;}
}
int p = 0,k = -1;
for (int i = l; i <= r; i++) {
if (s[i] == '(') {++p; continue;}
if (s[i] == ')') {--p; continue;}
if (p) continue;
k = i; break;
}
if (k == -1) {Build(now,l+1,r-1); return;}
lc[now] = ++cnt; Build(cnt,l,k-1);
rc[now] = ++cnt; Build(cnt,k+1,r);
if (s[k] == '&') typ[now] = 9;
else if (s[k] == '|') typ[now] = 10;
else typ[now] = 11;
}
void fwt_and(int *A)
{
for (int i = 0; i < T; i++)
for (int j = 0; j < maxm; j++) {
if (j&(1<<i)) continue;
int u = A[j],v = A[j|(1<<i)];
A[j] = (u + v) % mo; A[j|(1<<i)] = v;
}
}
void ifwt_and(int *A)
{
for (int i = 0; i < T; i++)
for (int j = 0; j < maxm; j++) {
if (j&(1<<i)) continue;
int u = A[j],v = A[j|(1<<i)];
A[j] = (u - v + mo) % mo; A[j|(1<<i)] = v;
}
}
void fwt_or(int *A)
{
for (int i = 0; i < T; i++)
for (int j = 0; j < maxm; j++) {
if (j&(1<<i)) continue;
int u = A[j],v = A[j|(1<<i)];
A[j] = u; A[j|(1<<i)] = (v + u) % mo;
}
}
void ifwt_or(int *A)
{
for (int i = 0; i < T; i++)
for (int j = 0; j < maxm; j++) {
if (j&(1<<i)) continue;
int u = A[j],v = A[j|(1<<i)];
A[j] = u; A[j|(1<<i)] = (v - u + mo) % mo;
}
}
void Work(int now)
{
if (typ[now] < 9) {
for (int i = 0; i < maxm; i++) {
memset(ti,0,sizeof(ti));
for (int j = 0; j < 16; j++) {
for (int k = 0; k < 4; k++)
va[k] = (j>>k)&1,va[k+4] = va[k]^1;
int E = (i>>j)&1;
if (typ[now] < 8) {
if (va[typ[now]] == E) ++ti[typ[now]];
continue;
}
for (int k = 0; k < 8; k++)
if (va[k] == E) ++ti[k];
}
int tot = 0;
for (int I = 0; I < 8; I++)
if (ti[I] == 16) ++tot;
f[now][i] = tot;
}
return;
}
Work(lc[now]); Work(rc[now]);
if (typ[now] == 9) {
fwt_and(f[lc[now]]);
fwt_and(f[rc[now]]);
for (int i = 0; i < maxm; i++)
f[now][i] = 1LL*f[lc[now]][i]*f[rc[now]][i]%mo;
ifwt_and(f[now]);
}
else if (typ[now] == 10) {
fwt_or(f[lc[now]]);
fwt_or(f[rc[now]]);
for (int i = 0; i < maxm; i++)
f[now][i] = 1LL*f[lc[now]][i]*f[rc[now]][i]%mo;
ifwt_or(f[now]);
}
else {
fwt_and(f[lc[now]]);
fwt_and(f[rc[now]]);
for (int i = 0; i < maxm; i++)
f[now][i] = 1LL*f[lc[now]][i]*f[rc[now]][i]%mo;
ifwt_and(f[now]);
ifwt_and(f[lc[now]]);
ifwt_and(f[rc[now]]);
fwt_or(f[lc[now]]);
fwt_or(f[rc[now]]);
memset(g,0,sizeof(g));
for (int i = 0; i < maxm; i++)
g[i] = 1LL*f[lc[now]][i]*f[rc[now]][i]%mo;
ifwt_or(g);
for (int i = 0; i < maxm; i++)
f[now][i] = (f[now][i] + g[i]) % mo;
}
}
bool Judge(int x)
{
for (int j = 0; j < 16; j++) {
if (Mark[j] == -1) continue;
for (int k = 0; k < 4; k++)
va[k] = (j>>k)&1,va[k+4] = va[k]^1;
int E = (x>>j)&1;
if (Mark[j] != E) return 0;
}
return 1;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
scanf("%s",s + 1);
n = strlen(s + 1);
memset(Mark,-1,sizeof(Mark));
cin >> m;
while (m--) {
int A,B,C,D,E;
scanf("%d%d%d%d%d",&A,&B,&C,&D,&E);
int G = A + (B<<1) + (C<<2) + (D<<3);
Mark[G] = E;
}
Build(1,1,n);
Work(1);
for (int i = 0; i < maxm; i++)
if (Judge(i))
ans = (ans + f[1][i]) % mo;
cout << ans;
return 0;
}