[BZOJ5285][二进制]HNOI2018:寻宝游戏

版权声明:虽然博主很菜,但是还是请注明出处(我觉得应该没人偷我的博客) https://blog.csdn.net/qq_43346903/article/details/88048954

BZOJ5285

一个很妙的做法:
我们都很清楚&1和|0是没有用的,所以我们可以发现,如果把&看成1,|看成0,则一个使某一位运算结果为1的& 和 | 组成的二进制序列必须小于所有数的这一位组成的序列
所以就排个序查就行了

Code:

#include<bits/stdc++.h>
#define mod 1000000007
using namespace std;
inline int read(){
	int res=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
	while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
	return res*f;
}
const int N=1005,M=5005;
char s[M];
int n,m,q,bin[N],pos[M];
struct str{int id,wei[N],val;}b[M];
inline bool cmp(str a,str b){
    for(int i=n-1;i>=0;i--){
        if(a.wei[i]>b.wei[i]) return 1;
        else if(a.wei[i]<b.wei[i]) return 0;
	}
	return 0;
}
int main(){
  	n=read();m=read();q=read();
    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",s+1);
        for(int j=1;j<=m;j++) 
            b[j].wei[i]=s[j]-'0',(b[j].val+=b[j].wei[i]*bin[i])%=mod;
    }
    for(int i=1;i<=m;i++) b[i].id=i;
    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",s+1);
        int minn=m+1,maxn=0;
        for(int i=1;i<=m;i++)
            if(s[i]=='0') minn=min(minn,pos[i]);
            else maxn=max(maxn,pos[i]);
        if (maxn>minn) puts("0");
        else cout<<(b[maxn].val+mod-b[minn].val)%mod<<"\n";
    }
}

猜你喜欢

转载自blog.csdn.net/qq_43346903/article/details/88048954
今日推荐