好神仙的题目啊……
二进制下,\(\land 1\)与\(\lor 0\)实际上是没有意义的,而\(\land 0\)强制这一位变为\(0\),\(\lor 1\)强制这一位变为\(1\)
那么如果某一位的答案要为\(0\),也就意味着:要么同时不存在\(\land 0\)与\(\lor 1\),要么最后一个\(\land 0\)后面不能有\(\lor 1\)。答案为\(1\)同理。
那么对于每一位,将所有\(a_i\)在这一位上的值从右往左看作一个二进制数\(x\),将操作序列\(\land\)对应为\(1\)、\(\lor\)对应为\(0\),从右往左看作一个二进制数\(op\),那么如果答案的这一位为\(0\),必须满足\(op \geq x\)。反之则要满足\(op < x\)。
那么最后的答案就会表现为\(a \leq op < b\)的形式,答案为\(b-a\)。
那么将所有\(x\)排好序,每一次扫一遍找到\(a\)和\(b\)就可以了。注意可能出现\(a>b\)的情况。
#include<bits/stdc++.h>
//This code is written by Itst
using namespace std;
inline int read(){
int a = 0;
char c = getchar();
bool f = 0;
while(!isdigit(c)){
if(c == '-')
f = 1;
c = getchar();
}
while(isdigit(c)){
a = (a << 3) + (a << 1) + (c ^ '0');
c = getchar();
}
return f ? -a : a;
}
const int MOD = 1e9 + 7;
int val[5010] , ind[5010] , tmp[5010];
int N , M , Q , cnt[2];
char s[5010];
int main(){
#ifndef ONLINE_JUDGE
//freopen("in" , "r" , stdin);
//freopen("out" , "w" , stdout);
#endif
N = read();
M = read();
Q = read();
for(int i = 1 ; i <= M ; ++i)
ind[i] = i;
int times = 1;
for(int i = 1 ; i <= N ; ++i){
scanf("%s" , s + 1);
cnt[0] = cnt[1] = 0;
for(int j = 1 ; j <= M ; ++j)
if(s[j] == '0')
++cnt[1];
else
val[j] = (val[j] + times) % MOD;
for(int j = 1 ; j <= M ; ++j)
tmp[++cnt[s[ind[j]] - '0']] = ind[j];
memcpy(ind , tmp , sizeof(int) * (M + 1));
times = (times << 1) % MOD;
}
for(int i = 1 ; i <= Q ; ++i){
scanf("%s" , s + 1);
int L = 0 , R = times , indl = 0 , indr = M + 1;
for(int j = M ; j ; --j)
if(s[ind[j]] == '0'){
indl = j;
L = val[ind[j]];
break;
}
for(int j = 1 ; j <= M ; ++j)
if(s[ind[j]] == '1'){
indr = j;
R = val[ind[j]];
break;
}
if(indr < indl)
cout << 0 << '\n';
else
cout << (R - L + MOD) % MOD << '\n';
}
return 0;
}