Description
Solution
把输入的 (n) 个二进制数看作一个大小为 (n*m) 的矩阵
把每一列压成一个二进制数,其中最高位是最下面的元素
然后就有了 (m) 个二进制数 (b_i),然后逐位考虑
我们把操作序列也变成一个二进制数 (x),(1) 为 (&),(0) 为 (|)
那么第 (i) 位最后的结果为 (1) 当且仅当 (x<b_i) (注意最高位是最下面的元素)
然后就是确定 (x) 的取值范围了
如果我们把 (b) 数组从大到小排序,如果确定了 (x) ,那么就相当与把 (b) 从某个地方断开,前面的二进制位变成 (1),后面的变成 (0)
考虑每一个询问: (r_i)
首先满足条件的情况一定是:在 (b) 数组中,(r) 中所有的 (1) 位都在 (0) 位前面
找到断点 (i) 之后,答案就是 (b[i-1]-b[i]) 了
#include<bits/stdc++.h>
using namespace std;
const int N=5010,mod=1000000007;
int n,m,Q,p[N];char s[N];
struct data{
bool b[1010];int id;
inline bool operator <(const data &p)const{
for(int i=n;i>=1;i--)
if(b[i]!=p.b[i])return b[i]>p.b[i];
return id<p.id;
}
}a[N];
bool w[N];
inline int putans(int x){
int ret=0,t=0;
for(int i=n;i>=1;i--)
ret=(1ll*ret*2+a[x-1].b[i])%mod;
for(int i=n;i>=1;i--)
t=(1ll*t*2+a[x].b[i])%mod;
ret=(ret-t+mod)%mod;
return ret+(x==1);
}
int main(){
freopen("hunt.in","r",stdin);
freopen("hunt.out","w",stdout);
cin>>n>>m>>Q;
for(int i=1;i<=n;i++){
scanf("%s",s+1);
for(int j=1;j<=m;j++)a[j].b[i]=s[j]-'0';
}
for(int i=1;i<=m;i++)a[i].id=i;
sort(a+1,a+m+1);
for(int i=1;i<=m;i++)p[a[i].id]=i;
for(int i=1;i<=n;i++)a[0].b[i]=1;
while(Q--){
scanf("%s",s+1);
for(int i=1;i<=m;i++)w[p[i]]=s[i]-'0';
bool t=0,flag=0;
for(int i=1;i<=m;i++){
if(t && w[i]){flag=1;break;}
t=w[i]^1;
}
if(flag)puts("0");
else{
for(int i=1;i<=m+1;i++){
if(w[i]==0){
printf("%d
",putans(i));
break;
}
}
}
}
return 0;
}