Luogu4424 HNOI/AHOI2018 寻宝游戏 神仙题

传送门


好神仙的题目啊……

二进制下,\(\land 1\)\(\lor 0\)实际上是没有意义的,而\(\land 0\)强制这一位变为\(0\)\(\lor 1\)强制这一位变为\(1\)

那么如果某一位的答案要为\(0\),也就意味着:要么同时不存在\(\land 0\)\(\lor 1\),要么最后一个\(\land 0\)后面不能有\(\lor 1\)。答案为\(1\)同理。

那么对于每一位,将所有\(a_i\)在这一位上的值从右往左看作一个二进制数\(x\),将操作序列\(\land\)对应为\(1\)\(\lor\)对应为\(0\),从右往左看作一个二进制数\(op\),那么如果答案的这一位为\(0\),必须满足\(op \geq x\)。反之则要满足\(op < x\)

那么最后的答案就会表现为\(a \leq op < b\)的形式,答案为\(b-a\)

那么将所有\(x\)排好序,每一次扫一遍找到\(a\)\(b\)就可以了。注意可能出现\(a>b\)的情况。

#include<bits/stdc++.h>
//This code is written by Itst
using namespace std;

inline int read(){
    int a = 0;
    char c = getchar();
    bool f = 0;
    while(!isdigit(c)){
        if(c == '-')
            f = 1;
        c = getchar();
    }
    while(isdigit(c)){
        a = (a << 3) + (a << 1) + (c ^ '0');
        c = getchar();
    }
    return f ? -a : a;
}

const int MOD = 1e9 + 7;
int val[5010] , ind[5010] , tmp[5010];
int N , M , Q , cnt[2];
char s[5010];

int main(){
    #ifndef ONLINE_JUDGE
    //freopen("in" , "r" , stdin);
    //freopen("out" , "w" , stdout);
    #endif
    N = read();
    M = read();
    Q = read();
    for(int i = 1 ; i <= M ; ++i)
        ind[i] = i;
    int times = 1;
    for(int i = 1 ; i <= N ; ++i){
        scanf("%s" , s + 1);
        cnt[0] = cnt[1] = 0;
        for(int j = 1 ; j <= M ; ++j)
            if(s[j] == '0')
                ++cnt[1];
            else
                val[j] = (val[j] + times) % MOD;
        for(int j = 1 ; j <= M ; ++j)
            tmp[++cnt[s[ind[j]] - '0']] = ind[j];
        memcpy(ind , tmp , sizeof(int) * (M + 1));
        times = (times << 1) % MOD;
    }
    for(int i = 1 ; i <= Q ; ++i){
        scanf("%s" , s + 1);
        int L = 0 , R = times , indl = 0 , indr = M + 1;
        for(int j = M ; j ; --j)
            if(s[ind[j]] == '0'){
                indl = j;
                L = val[ind[j]];
                break;
            }
        for(int j = 1 ; j <= M ; ++j)
            if(s[ind[j]] == '1'){
                indr = j;
                R = val[ind[j]];
                break;
            }
        if(indr < indl)
            cout << 0 << '\n';
        else
            cout << (R - L + MOD) % MOD << '\n';
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Itst/p/10324748.html