首页 > 其他 > 详细

[HNOI2018]寻宝游戏

时间:2019-03-14 21:53:04      阅读:187      评论:0      收藏:0      [点我收藏+]

[Luogu4424] [BZOJ5285]

myy的官方题解

洛谷题解

感谢寻大爷的帮助

\(1.\)把操作序列转化为2进制数,手动模拟的时候把相同性质的放到一起考虑(\(1\)\(|,0\)\(&\))&;&有的时候也需要把性质不同的放到一起

\(2.\)确定范围只需要通过两个边界

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define Debug(x) cout<<#x<<"="<<x<<endl
using namespace std;
typedef long long LL;
const int INF=1e9+7;
inline LL read(){
    register LL x=0,f=1;register char c=getchar();
    while(c<48||c>57){if(c=='-')f=-1;c=getchar();}
    while(c>=48&&c<=57)x=(x<<3)+(x<<1)+(c&15),c=getchar();
    return f*x;
}

const int MAXN=5e3+5;
const int mod=1e9+7;

int a[MAXN],b[MAXN],f[MAXN],g[MAXN],pow[MAXN];
char s[MAXN];
int n,m,Q,cnt[2];

int main(){
    n=read(),m=read(),Q=read();
    pow[0]=1;
    for(int i=1;i<=n;i++) pow[i]=(pow[i-1]*2)%mod;
    for(int i=1;i<=m;i++) a[i]=i;//初值只要都存在就行了
    for(int i=1;i<=n;i++){
        scanf("%s",s+1);
        cnt[0]=0,cnt[1]=m;
        for(int j=1;j<=m;j++)
            if(s[j]=='1') f[j]=(f[j]+pow[i-1])%mod;
            else cnt[0]++;
        for(int j=m;j>=1;j--) b[cnt[s[a[j]]-'0']--]=a[j];//2进制基数排序,先排低位,再排高位
        swap(a,b);
    }
    for(int i=1;i<=m;i++) g[i]=f[a[i]];
    g[m+1]=pow[n];
    while(Q--){
        // x>op --> 1
        // x<=op --> 0
        // 通过两个临界状态确定范围(还是觉得有点怪)
        scanf("%s",s+1);
        int up=m+1,down=0;
        for(int i=m;i>=1;i--)
            if(s[a[i]]=='0'){down=i;break;}//最大的一个要变成0 --> op要大于这个最大数
        for(int i=1;i<=m;i++)
            if(s[a[i]]=='1'){up=i;break;}//最小的一个要变成1 --> op要小于这个数
        if(up<down) printf("0\n");
        else printf("%d\n",(g[up]-g[down]+mod)%mod);
    }
}

[HNOI2018]寻宝游戏

原文:https://www.cnblogs.com/lizehon/p/10533647.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!