懶惰成性
php
PS:and和or運算符在這道題裏面是相同優先級的spa
顯然&1或者|0都是沒有意義的操做code
咱們把運算符也當成01,&表示1,|表示0xml
這樣子對於一個運算式,就能夠轉成一個01字符串了blog
咱們能夠一列一列處理值排序
若某一列的最終值爲1,則須要知足最後一個|1的位置出如今最後一個&0的位置後面字符串
爲0,則須要知足最後一個&0的位置要出如今最後一個|1的位置後面get
能夠發現,使結果爲1的運算串爲全部字典序小於當前位構成的01串的01串string
那麼結果爲0的運算串就是除告終果爲1的運算串以外的01串it
那麼咱們就能獲得每一列運算串的範圍
而後咱們只要取出全部列構成的運算串的範圍的公共部分就好了
由於若是直接將01串轉成數字太大了,因此若是要比較兩個01串的大小就要用基數排序來肯定順序,從而肯定大小
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> using namespace std; typedef long long LL; char st[5100]; LL pw[1100],Mod=1e9+7,to1[5100]; int Rank[5100],cnt[2],tt[5100]; int main() { int n,m,q; scanf("%d%d%d",&n,&m,&q); pw[1]=1; for(int i=2;i<=n+1;i++) pw[i]=(pw[i-1]<<1)%Mod; for(int i=1;i<=m;i++) Rank[i]=i; for(int i=1;i<=n;i++) { scanf("%s",st+1); cnt[0]=cnt[1]=0; for(int j=1;j<=m;j++) { to1[j]=(to1[j]+LL(st[j]-'0')*pw[i])%Mod; cnt[st[j]-'0']++; } cnt[1]+=cnt[0]; for(int j=m;j>=1;j--) tt[cnt[st[Rank[j]]-'0']--]=Rank[j]; for(int j=1;j<=m;j++) swap(tt[j],Rank[j]); } reverse(Rank+1,Rank+m+1); while(q--) { scanf("%s",st+1); int l=0,r=m+1; for(int i=m;i>=1;i--) { if(st[Rank[i]]=='1') { r=i;break; } } for(int i=1;i<=m;i++) { if(st[Rank[i]]=='0') { l=i;break; } } if(l==0) printf("%lld\n",to1[Rank[r]]); else if(r==m+1) printf("%lld\n",(pw[n+1]-to1[Rank[l]]+Mod)%Mod); else if(l>=r) printf("%lld\n",(to1[Rank[r]]-to1[Rank[l]]+Mod)%Mod); else printf("0\n"); } return 0; }