【BZOJ】5285: [Hnoi2018]尋寶遊戲 -找規律/拆位
阿新 • • 發佈:2018-11-29
傳送門:bzoj5285
題解
首先考慮拆出一位來觀察性質:
和
不會使原數變化。
和
會使原數變為
/
,而與原數無關。
可以把操作看做一個01串 ,而設 為1-n的原串中這一位取出來得到的01串。若 中連續一段 與 相等,則經過這一段操作後仍存在值 。
若值最後
,則必然
出現在
之後。
將第
位作為最高位,要求就變成了
。
若值最後 ,則 。直接統計即可。
程式碼
#include<bits/stdc++.h>
using namespace std;
const int N=5010,mod=1e9+7;
int n,m,qe,a[N],b[N],s[N],bin[N],c[2];
char q[N];
inline int ad(int x,int y){x+=y;return x>=mod?x-mod:x;}
inline int dc(int x,int y){x-=y;return x<0?x+mod:x;}
int main(){
int i,j,l,r;
scanf("%d%d%d",&n,&m,&qe);
for(i=1;i<=m;++i) a[i]=i;
bin[1]=1;for(i=2;i<=n;++i) bin[i]=ad(bin[i-1],bin[i-1]);
for(i=1;i<=n;++i){
scanf("%s",q+1);c[1]=m;c[0]=0;
for(j=1;j<=m;++j) q[j]=='1'?(s[j]=ad(s[j],bin[i])):(c[0]++);
for(j=m;j;--j) b[c[q[a[j]]-'0']--]=a[j];
for(j=1;j<=m;++j) a[j]=b[j];
}
s[m+1]=ad(bin[n],bin[n]);a[m+1]=m+1;
for(;qe;--qe){
scanf("%s",q+1);l=0;r=m+1;
for(i=m;i;--i) if(q[a[i]]=='0') {l=i;break;}
for(i=1;i<=m;++i) if(q[a[i]]=='1') {r=i;break;}
printf("%d\n",l>=r?0:dc(s[a[r]],s[a[l]]));
}
return 0;
}