大致题意:给你n个01串,可以在每个串之间填&或者|(与或者或)运算符号,有q个询问,对于每个询问,回答运算结果为询问值的方案数。(第一个数前有一个不存在的0,所以共需要填n个运算符号)。
这个输入其实有助于你去思考。如果我来改这道题我会全部输入十进制整数。
首先有个反应就是按位处理。主要是不按位处理没法做的鸭子。
某一位的取值相当于对应列按照运算符号运算出来的值。也就是说要在n个0/1之间填符号,达到一个0/1。
考虑怎么得到一个0/1。如果是0,那最后一个&0一定在最后一个|1后面。反之,在前面。
而|0和&1这两个运算对结果没有任何影响。
如果我们设或运算为0,与运算为1,把操作弄成一行,我们就得到了一个操作串。
对于操作串,我们发现,如果原串某一位和操作串对应相等,那就没有贡献(|0和&1没有贡献)
反之,就有大小之分。对于结果为1,我们发现,最后一个|1要在最后一个&0后面。
前后翻转,第一个|1要在第一个&0前面。按照原串/操作的顺序,就是第一个1/0要出现在第一个0/1前。
那不就是说原串比操作串要大么。
所以总结来说,我们将每一位对应的那一列,从下往上反着形成的串提取出来。如果对应的这一位答案要为1,那操作串应当小于这个串。反之大于等于。
那将这些串sort一遍,对于所有1,我们要小于最小的,对于所有0,我们要大于等于最大的。
两者之差,便是操作串的所有方案。负数就是0。
注意变量名的区分,我被挂了一小时。
#include<bits/stdc++.h>
using namespace std;
#define in read()
#define int long long
int in{
int cnt=0,f=1;char ch=0;
while(!isdigit(ch)){
ch=getchar();if(ch=='-')f=-1;
}
while(isdigit(ch)){
cnt=cnt*10+ch-48;
ch=getchar();
}return cnt*f;
}
const int mod=1e9+7;
int n,m,q;
int a[1003][5003];
struct node{
int a[1003];
int id,key;
}b[5003];
bool cm(node a,node b){
for(int i=n;i>=1;i--){
if(a.a[i]!=b.a[i])return a.a[i]<b.a[i];
}return 1;
}
char ch[5003];
int que[5003];
int ksm(int a,int b){
int sum=1;
while(b){
if(b&1)sum=sum*a%mod;a=a*a%mod;b>>=1;
}return sum;
}
signed main(){
n=in;m=in;q=in;
for(int i=1;i<=n;i++){
scanf("%s",ch+1);
for(int j=1;j<=m;j++){
a[i][j]=(ch[j]=='1');
}
}
for(int i=1;i<=m;i++){
for(int j=n;j>=1;j--){
b[i].a[j]=a[j][i];b[i].key=(b[i].key*2%mod+b[i].a[j])%mod;
}
b[i].id=i;
}
// cout<<"###"<<endl;
// for(int i=1;i<=m;i++){
// for(int j=n;j>=1;j--)cout<<b[i].a[j];cout<<endl;
// }cout<<"###"<<endl;
sort(b+1,b+m+1,cm);//升序sort。
// cout<<"###"<<endl;
// for(int i=1;i<=m;i++){
// cout<<b[i].id<<" "<<b[i].key;cout<<endl;
// }cout<<"###"<<endl;
b[m+1].key=ksm(2,n);
int l=0,r=0;
while(q--){
l=r=0;
scanf("%s",ch+1);
for(int i=1;i<=m;i++)que[i]=(ch[i]=='1');
for(int i=m;i>=1;i--){
if(que[b[i].id]==0){
l=i;break;
}
}
for(int i=1;i<=m;i++){
if(que[b[i].id]==1){
r=i;break;
}
}if(r==0)r=m+1;
// cout<<l<<" "<<r<<endl;
// cout<<b[l].key<<" "<<b[r].key<<endl;
// for(int i=n;i>=1;i--)cout<<b[r].a[i]<<" ";cout<<endl;for(int i=n;i>=1;i--)cout<<b[l].a[i]<<" ";cout<<endl;
if(l>r&&l&&r)cout<<"0"<<'\n';
//else if(l==r&&r==0)cout<<b[0].key<<'\n';
else cout<<(b[r].key-b[r-1].key+mod)%mod<<'\n';
}
return 0;
}
/*
8 10 3
0100011011
0110100101
1100011110
0001110100
0001101110
0110100001
1110001010
0010011101
0110011111
1101001010
0010001001
*/