题意:
分析:
-
暴力 (O(qn imes 2^m))
-
正解:
stO 考场上直接切掉这道题的巨佬们,蒟蒻瑟瑟发抖
我们按照操作和数字的组合分清况来讨论:
(1 & 0 o 0) (1|0 o 1) (1 & 1 o 1) (1|1 o 1)
(0 & 0 o 0) (0|0 o 0) (0&1 o 0) (0|1 o 1)
我们观察发现第二列和第三列有一些特殊性质:
即 (|0) 和 (&1) 的组合不会对原来的值产生任何影响 而 (|1) 相当于赋值为 (1) ,(& 0) 相当于赋值为 (0)
关键的一步来了,我们对操作进行转化,因为操作只有 (& |) 两种,和 (0,1) 一样,那么我们考虑将操作也转化成 (0,1) 序列, 我们把 (|) 看做 (0) , $& $ 看成 (1)
这样一来,我们就能通过操作的大小关系来判断出最后每一位的结果,我们按位 考虑,对于每一位从 (n) 到 (1) 看成一个从高到低的二进制数字序列,从 (n) 到 (1) 的操作看成从高到低的二进制操作序列,如果操作序列和数字序列某一位相同,那么没有任何影响,如果操作序列某一位小于数字序列,相当于赋值为 (1) ,如果操作序列某一位大于数字序列,相当于赋值为 (0) 由于后来的操作会覆盖开始的操作,所以高位的答案会覆盖低位的答案,这和二进制下的大小一样,高位操作优先,所以我们发现,当
- 操作序列小于数字序列,这一位为 (1) ( 不能是等于数字序列,是因为最开始这一位为 (0) ,必须要有 (|1) 操作)
- 操作序列大于等于数字序列,这一位为 (0)
然后我们对于原序列每一位,建出数字序列,然后根据查询串的 (0,1) 关系,判断出操作序列的上界和下界,之间的每一种操作都可以取到
代码:
#include<bits/stdc++.h>
#define pii pair<int,int>
#define mk(x,y) make_pair(x,y)
#define lc rt<<1
#define rc rt<<1|1
#define pb push_back
#define fir first
#define sec second
#define inl inline
#define reg register
using namespace std;
namespace zzc
{
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
const int maxn = 5005;
const int mod = 1e9+7;
int n,m,q;
string s[maxn],r;
int rk[maxn],seq[maxn];
char ch;
bool cmp(int x,int y)
{
return s[x]<s[y];
}
long long calc(string &a,string &b)
{
long long bas=1,res=0;
for(int i=n-1;i>=0;i--)
{
res=(res+bas*(a[i]+mod-b[i])%mod)%mod;
bas=bas*2%mod;
}
return res;
}
void work()
{
n=read();m=read();q=read();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
ch=getchar();
while(ch!='0'&&ch!='1') ch=getchar();
s[j]+=ch;
}
}
for(int i=1;i<=m;i++) reverse(s[i].begin(),s[i].end());
for(int i=1;i<=n;i++) s[0]+='0',s[m+1]+='1';
for(int i=1;i<=m+1;i++) seq[i]=i;
sort(seq+1,seq+m+1,cmp);
for(int i=1;i<=m+1;i++) rk[seq[i]]=i;
while(q--)
{
cin>>r;
int dwn=0,upn=m+1;
for(int i=1;i<=m;i++)
{
if(r[i-1]=='0') dwn=max(dwn,rk[i]);
else upn=min(upn,rk[i]);
}
if(dwn>upn) puts("0");
else printf("%lld
",(1ll*(upn==m+1)?1:0)+calc(s[seq[upn]],s[seq[dwn]]));
}
}
}
int main()
{
zzc::work();
return 0;
}