视最后一个数为最高位,把操作符视作 01 串(&
\(\rightarrow\) 1
,|
\(\rightarrow\) 0
),记做 \(opt\)。
视最后一个数为最高位,把 \(n\) 个长度为 \(m\) 的 01 串按位拆成 \(m\) 个长度为 \(n\) 的 01 串,记做 \(x_i\)。
发现第 \(i\) 位为 \(0\),当且仅当 \(opt \geq x_i\);第 \(i\) 位为 \(1\),当且仅当 \(opt \le x_i\)。
把 \(m\) 个约束合并,就可以得到形如 \(l \leq opt \le r\) 的不等式,答案即为 \(r - l\)。
#pragma GCC optimize(2)
#include <cstdio>
#include <cstring>
const int MOD = 1e9 + 7, MAXN = 1e3 + 19, MAXM = 5e3 + 19;
int n, m, q;
char str[MAXM];
bool bit[MAXM][MAXN];
int l, r, ans;
int p[MAXN];
bool less(bool* a, bool* b){
for(int i = n; i >= 1; --i)
if(a[i] != b[i])
return a[i] < b[i];
return false;
}
bool greater(bool* a, bool* b){
for(int i = n; i >= 1; --i)
if(a[i] != b[i])
return a[i] > b[i];
return false;
}
bool greater_equal(bool* a, bool* b){
for(int i = n; i >= 1; --i)
if(a[i] != b[i])
return a[i] > b[i];
return true;
}
int main(){
std::scanf("%d%d%d", &n, &m, &q);
p[0] = 1;
for(int i = 1; i < n; ++i)
p[i] = (p[i - 1] << 1) % MOD;
for(int i = 1; i <= n; ++i){
std::scanf("%s", str + 1);
for(int j = 1; j <= m; ++j)
bit[j][i] = str[j] == '1';
}
std::memset(bit[m + 1], 0, sizeof bit[m + 1]);
std::memset(bit[m + 2], 0xff, sizeof bit[m + 1]);
while(q--){
std::scanf("%s", str + 1);
l = m + 1, r = m + 2, ans = 1;
for(int i = 1; i <= m; ++i){
if(str[i] == '0')
less(bit[l], bit[i]) ? l = i : 0;
else if(str[i] == '1'){
greater(bit[r], bit[i]) ? r = i : 0;
ans = 0;
}
}
if(greater_equal(bit[l], bit[r])){
std::puts("0");
continue;
}
for(int i = 1; i <= n; ++i){
if(bit[l][i])
ans = (ans - p[i - 1]) % MOD;
if(bit[r][i])
ans = (ans + p[i - 1]) % MOD;
}
ans = (ans + MOD) % MOD;
std::printf("%d\n", ans);
}
return 0;
}