https://www.lydsy.com/JudgeOnline/problem.php?id=5285php
|0 和 &1 沒有影響spa
若填‘|’,記爲0,若填‘&’,記爲1code
先只考慮最後一位blog
若要求最後=1get
那麼最後一個|1 要在最後一個 &0 後面it
將n個數的最後一位拿出來構成一個01序列io
填在全部數最後一位以前的運算符也拿出來構成一個01序列class
將第n個數所在位置視爲最高位di
對於最高位來講co
若是數字序列 和 運算符序列 都是0或都是1,沒有影響
若是數字序列是0,運算符序列是1,即最後是 &0,顯然不能最終等於1,因此這種運算符序列不合法
若是數字序列是1,運算符序列是0,及最後是|1,顯然必定是1,這種運算符序列合法
若是數字序列始終等於運算符序列,由於沒有影響,因此最終開始開始的那個0,此運算符序列也不合法
因此
若是這一位要求是1,在只考慮這一位的狀況下,合法的運算符序列是 運算符的01序列<數字的01序列
同理能夠推出
若是這一位要求是0,在只考慮這一位的狀況下,合法的運算符序列是 運算符的01序列>=數字的01序列
便可以獲得這樣的條件:
設合法的運算符序列爲S,第i位的數字序列爲Ai
若p的第i位爲1,則S<Ai ①
若p的第i位爲0,則S>=Ai ②
記①中最小的Ai爲 up,②中最大的Ai爲down
因此知足全部位的要求的S的個數=up-down
計算個數開始想的是高精減,題目要求取模,直接哈希便可
#include<cstdio> #include<algorithm> #define N 5001 using namespace std; const int mod=1e9+7; int bit[N]; char s[N]; int has[N]; int sa[N],now[N]; int main() { int n,m,q; scanf("%d%d%d",&n,&m,&q); bit[0]=1; for(int i=1;i<=n;++i) { bit[i]=bit[i-1]<<1; bit[i]-=bit[i]>=mod ? mod : 0; } for(int i=1;i<=m;++i) sa[i]=i; int c[2]; for(int i=1;i<=n;++i) { c[1]=c[0]=0; scanf("%s",s+1); for(int j=1;j<=m;++j) { has[j]=has[j]+(s[j]-'0')*bit[i-1]; has[j]-=has[j]>=mod ? mod : 0; c[s[j]-'0']++; } c[1]+=c[0]; for(int j=m;j;--j) now[c[s[sa[j]]-'0']--]=sa[j]; swap(sa,now); } int up,down; for(int t=1;t<=q;++t) { up=m+1; down=0; scanf("%s",s+1); for(int i=1;i<=m && up==m+1;++i) if(s[sa[i]]-'0') up=i; for(int i=m;i && !down;--i) if(!(s[sa[i]]-'0')) down=i; if(up<down) { puts("0"); continue; } up= up==m+1 ? bit[n] : has[sa[up]]; down= !down ? 0 : has[sa[down]]; printf("%d\n",(up-down+mod)%mod); } }