LOJ#2494. 「AHOI / HNOI2018」寻宝游戏

题目链接

分析

除了第一个数外,以编号最小的为最低位,把每一个数的第i位拿出来组成一个n位二进制数,设为bi。
对于所填的运算符,设or为0,and为1,拿出来也会组成一个nn位二进制数,设为x。
神奇的地方来了,该位运算结果为1当且仅当bi>x。
那么我们就可以把bibi从大到小排序,对于每个询问,其答案不为0当且仅当不存在某个1在0的后面。否则就找到第一个0,设为第i位,那么答案就是bi−1−bi。

Code

#include <bits/stdc++.h>

const int N = 1005;
const int M = 5005;
const int MOD = 1000000007;

int n,m,q,bin[N],pos[M];
struct data
{
    int id,s[N],val;
}b[M];
char str[M];

bool cmp(data a,data b)
{
    for (int i = n - 1; i >= 0; i--)
        if (a.s[i] > b.s[i]) 
            return 1;
        else if (a.s[i] < b.s[i]) 
            return 0;
    return 0;
}

int main()
{
    scanf("%d%d%d",&n,&m,&q);
    bin[0] = 1;
    for (int i = 1; i <= n; i++) 
        bin[i] = bin[i - 1] * 2 % MOD;
    for (int i = 0; i < n; i++)
    {
        scanf("%s",str + 1);
        for (int j = 1; j <= m; j++) 
            b[j].s[i] = str[j] - '0', (b[j].val += b[j].s[i] * bin[i]) %= MOD;
    }
    for (int i = 1; i <= m; i++) 
        b[i].id = i;
    std::sort(b + 1, b + m + 1, cmp);
    for (int i = 1; i <= m; i++) 
        pos[b[i].id] = i;
    b[0].val = bin[n];
    while (q--)
    {
        scanf("%s",str + 1);
        int mn = m + 1, mx = 0;
        for (int i = 1; i <= m; i++)
            if (str[i] == '0') 
                mn = std::min(mn,pos[i]);
            else mx = std::max(mx,pos[i]);
        if (mx > mn) 
            printf("%d\n",0);
        else printf("%d\n",(b[mx].val + MOD - b[mn].val) % MOD);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值