5285: [Hnoi2018]寻宝游戏
分析:
从下面依次确定运算符号,然后在确定的过程中,需要确定的位数会逐渐减少。比如最后有一个1,如果在从下往上确定了一个or 1,那么再往前可以随便选了。
那么就是要求从下往上,第一个出现的or 1要在and 0之前。如果将这一位上的每一个数字拿出来,从下往上构成一个二进制数a,把and看成1,or看成0,也是从下往上构成一个二进制数b,那么就是要求b<a。
对于最后是0的同样是这样,然后取一下中间可以选的范围即可。
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<cctype>
#include<set>
#include<vector>
#include<queue>
#include<map>
#define fi(s) freopen(s,"r",stdin);
#define fo(s) freopen(s,"w",stdout);
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = , mod = 1e9 + ;
struct Node{ int a[], val, id; } b[N];
int pos[N], n, m;
char s[N]; bool cmp(Node A,Node B) {
for (int i = n; i >= ; --i) {
if (A.a[i] > B.a[i]) return ;
else if (A.a[i] < B.a[i]) return ;
}
return ;
} int main() {
n = read(), m = read();int q = read();
for (int i = ; i <= n; ++i) {
scanf("%s", s + );
for (int j = ; j <= m; ++j) b[j].a[i] = s[j] - '';
}
for (int j = ; j <= m; ++j) {
for (int i = n; i >= ; --i) b[j].val = (b[j].val * % mod + b[j].a[i]) % mod;
b[j].id = j;
}
sort(b + , b + m + , cmp);
for (int i = ; i <= m; ++i) pos[b[i].id] = i;
b[].val = ;
for (int i = ; i <= n; ++i) b[].val = (b[].val * ) % mod;
while (q --) {
scanf("%s", s + );
int L = , R = m + ;
for (int i = ; i <= m; ++i) {
if (s[i] == '') R = min(R, pos[i]);
else L = max(L, pos[i]);
}
if (L > R) puts("");
else printf("%d\n", (b[L].val - b[R].val + mod) % mod);
}
return ;
}