AHOI/HNOI2018寻宝游戏

牛逼二进制


x&0=0,x|1=1

我们把(& o0,| o1),把操作用01串代替

于是转化为比大小的题目

桶排然后记录每个串的值方便求答案

时间复杂度(O(nm))

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return f==1?x:-x;
}
const int N=5004,mod=1e9+7;
int n,m,Q,mi[N],c[2],a[N],b[N],sa[N];
char s[N];
int main(){
	n=read();m=read();Q=read();
	mi[1]=1;
	for(int i=2;i<=n+1;i++)mi[i]=(mi[i-1]<<1)%mod;
	for(int i=1;i<=m;i++)sa[i]=i;
	for(int i=1;i<=n;i++){
		scanf("%s",s+1);
		reverse(s+1,s+m+1);
		c[1]=m;c[0]=0;
		for(int j=1;j<=m;j++)
			if(s[j]=='1')a[j]=(a[j]+mi[i])%mod;
			else c[0]++;
		for(int j=m;j;j--)
			b[c[s[sa[j]]^48]--]=sa[j];
		swap(b,sa);
	} 
	for(int i=1;i<=m;i++)b[i]=a[sa[i]];
	b[m+1]=mi[n+1];
	while(Q--){
		scanf("%s",s+1);
		reverse(s+1,s+m+1);
		int up=m+1,dw=0;
		for(int i=m;i;i--)
			if(s[sa[i]]=='0'){dw=i;break;}
		for(int i=1;i<=m;i++)
			if(s[sa[i]]=='1'){up=i;break;}
		if(up<dw)puts("0");
		else cout<<(b[up]-b[dw]+mod)%mod<<"
";
	}
	return (0-0);
}
原文地址:https://www.cnblogs.com/aurora2004/p/12600694.html