P9393 紫丁香 题解
提供一种与其他题解不同的处理方法。
操作的性质看起来不怎么样,正难则反,套路地考虑如果倒过来操作会怎样(以下称其为“逆操作”):对于一个询问
如果对一个二进制数
显然不能对于每个二进制数都做一遍所有能做的逆操作(这样的枚举量是
于是最终的操作过程必然形如:
最后对于每个询问按照文章开头描述的方法进行求解。时间复杂度
放代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int m,n,q; cin>>m>>n>>q;
vector<int> a(1<<m);
iota(a.begin(),a.end(),0);
for(int i=0;i<n;i++){
string t; cin>>t;
int s=0,c=0;
for(char j:t)(s<<=1)|=j!='0',(c<<=1)|=j=='-';
a[s]&=c;
} // 考虑每次逆操作的影响
for(int S=(1<<m)-1;~S;S--)
for(int i=0;i<m;i++)
if(!(S>>i&1))a[S]&=a[S|1<<i]; // 高维后缀 and
for(auto &x:a)x=a[x];
while(q--){
string t; cin>>t;
int w=0,s=0;
for(char i:t)(w<<=1)|=i&1;
for(int i=m-1;~i;i--)
cout<<((a[s|1<<i]|w)==w?(s|=1<<i,1):0); // 类似二分的过程
cout<<'\n';
}
return 0;
}