[HNOI 2018] Scavenger Hunt

Description

Question bank link

Given \(n\) \(m\) bit binary numbers, insert an &or |, the \(0\ ) th number is \(0\) , \(0,1\) Insert symbols between them, and insert \(n\) symbols in total.

Given \(q\) groups of queries, each group of queries also gives a binary number, and asks how many ways can make the result of the operation from left to right be this number.

\ (1 \ leq n \ leq 1000,1 \ leq m \ leq 5000,1 \ leq q \ leq 1000 \)

Solution

Human Wisdom Questions.

We can take each bit out and process it separately, and press each bit into a binary number of \(n\) bits, and the \(i\)th bit is \(a_i\) . The further to the right the higher the number of digits.

We &denote as \(1\) and |denote as \(0\) . Likewise, the further to the right, the higher the number of digits. Denoted as \(x\) .

The test of human wisdom is that there is such a conclusion: if the result of the \(i\) bit operation is \(1\) , if and only if \(x<a_i\) . This can be understood intuitively.

Then we consider sorting \(a_i\) from large to small, we only need to find such a unique breakpoint, the one corresponding to the left \(a_i\) of the breakpoint is \(1\) , Anything to the right of the breakpoint is \(0\) .

Assuming that the one bit to the right of the breakpoint is \(loc\) , then the answer is \(a_{loc-1}-a_{loc}\) . If there is no breakpoint, there is obviously no solution.

Code

#include <bits/stdc++.h>
using namespace std;
const int N = 1000+5, M = 5000+5, yzh = 1000000007;

int n, m, q, mp[M], cg[M];
char ch[M];
struct tt {
    int b[N], id;
    bool operator < (const tt &c) const {
        for (int i = n; i >= 1; i--)
            if (b[i] != c.b[i]) return b[i] > c.b[i];
    }
}a[M];

int get_ans(int o) {
    int x = 0, y = 0;
    for (int i = n; i >= 1; i--) x = (2ll*x%yzh+a[o-1].b[i])%yzh;
    for (int i = n; i >= 1; i--) y = (2ll*y%yzh+a[o].b[i])%yzh;
    return ((x-y+(o == 1))%yzh+yzh)%yzh;
}
void work() {
    scanf("%d%d%d", &n, &m, &q);
    for (int i = 1; i <= n; i++) {
        scanf("%s", ch+1);
        for (int j = 1; j <= m; j++) a[j].b[i] = ch[j]-'0';
        a[0].b[i] = 1;
    }
    for (int i = 1; i <= m; i++) a[i].id = i;
    sort(a+1, a+m+1);
    for (int i = 1; i <= m; i++) mp[a[i].id] = i;
    while (q--) {
        scanf("%s", ch+1);
        for (int i = 1; i <= m; i++) cg[mp[i]] = ch[i]-'0';
        int flag = 0, t = 0;
        for (int i = 1; i <= m; i++) {
            if (cg[i] && t) {flag = 1; break; }
            if (cg[i] == 0) t = 1;
        }
        if (flag) puts("0");
        else {
            int flag = 0;
            for (int i = 1; i <= m; i++)
                if (cg[i] == 0) {printf("%d\n", get_ans(i)); flag = 1; break; }
            if (!flag) printf("%d\n", get_ans(m+1));
        }
    }
}
int main() {work(); return 0; }

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326560436&siteId=291194637