传送门:bzoj5285
当时出题的时候很紧张,是真的紧张,因为觉得实在是太水了。
我当时很怕结果出来十几个AC,全场70。然后就再也没人找我出题了。
当时就不停的想HNOI有什么水题,是不是比我这个更水来安慰自己。
----myy
题解
首先考虑拆出一位来观察性质:
o
r
0
or\ 0
or 0和
a
n
d
1
and \ 1
and 1不会使原数变化。
o
r
1
or\ 1
or 1和
a
n
d
0
and \ 0
and 0会使原数变为
1
1
1/
0
0
0,而与原数无关。
可以把操作看做一个01串 T ( 0 − > o r , 1 − > a n d ) T(0->or ,1->and) T(0−>or,1−>and),而设 S S S为1-n的原串中这一位取出来得到的01串。若 S S S中连续一段 [ l , r ] [l,r] [l,r]与 T T T相等,则经过这一段操作后仍存在值 = S l − 1 =S_{l-1} =Sl−1。
若值最后
=
1
=1
=1,则必然
o
r
1
or \ 1
or 1出现在
a
n
d
0
and\ 0
and 0之后。
将第
n
n
n位作为最高位,要求就变成了
S
>
T
S>T
S>T。
若值最后 = 0 =0 =0,则 S ≤ T S\leq T S≤T。直接统计即可。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=5010,mod=1e9+7;
int n,m,qe,a[N],b[N],s[N],bin[N],c[2];
char q[N];
inline int ad(int x,int y){x+=y;return x>=mod?x-mod:x;}
inline int dc(int x,int y){x-=y;return x<0?x+mod:x;}
int main(){
int i,j,l,r;
scanf("%d%d%d",&n,&m,&qe);
for(i=1;i<=m;++i) a[i]=i;
bin[1]=1;for(i=2;i<=n;++i) bin[i]=ad(bin[i-1],bin[i-1]);
for(i=1;i<=n;++i){
scanf("%s",q+1);c[1]=m;c[0]=0;
for(j=1;j<=m;++j) q[j]=='1'?(s[j]=ad(s[j],bin[i])):(c[0]++);
for(j=m;j;--j) b[c[q[a[j]]-'0']--]=a[j];
for(j=1;j<=m;++j) a[j]=b[j];
}
s[m+1]=ad(bin[n],bin[n]);a[m+1]=m+1;
for(;qe;--qe){
scanf("%s",q+1);l=0;r=m+1;
for(i=m;i;--i) if(q[a[i]]=='0') {l=i;break;}
for(i=1;i<=m;++i) if(q[a[i]]=='1') {r=i;break;}
printf("%d\n",l>=r?0:dc(s[a[r]],s[a[l]]));
}
return 0;
}