传送门
考虑枚举每个点作为起点,然后状压序列中的哪些位置可以在初始取任意值。
假设有
k
k
k个位置,那么这种状态的贡献为
2
k
2^k
2k。
但这样同一个状态会被算重。
于是我们考虑容斥来算。
注意剪枝。
代码:
#include<bits/stdc++.h>
#define ri register int
using namespace std;
typedef long long ll;
const int mogic=1e6+7;
class MapGuessing{
public:
struct Hash_table{
vector<ll>ori[mogic];
vector<int>tmp;
inline void clear(){for(ri i=tmp.size()-1;~i;--i)ori[tmp[i]].clear();}
inline bool query(ll x){
int t=x%mogic;
for(ri i=ori[t].size()-1;~i;--i)if(ori[t][i]==x)return 0;
if(!ori[t].size())tmp.push_back(t);
return ori[t].push_back(x),1;
}
}S;
vector<ll>sta;
inline int count(ll x){int ret=0;while(x)x^=x&-x,++ret;return ret;}
inline ll dfs(int pos,ll all,int coe){
if(pos==sta.size())return (ll)coe*(1ll<<count(all));
if(!all)return 0;
return dfs(pos+1,all,coe)+dfs(pos+1,all&sta[pos],coe!=1?1:-1);
}
int val[105];
inline ll countPatterns(string To,vector<string>Upd){
string upd;
S.clear();
sta.clear();
int n=To.size();
for(ri i=0;i<Upd.size();++i)upd=upd+Upd[i];
ll st,stat;
int l=0,r=0,t=0;
for(ri i=0;i<upd.size();++i){
if(upd[i]=='<')--t;
if(upd[i]=='>')++t;
l=min(l,t);
r=max(r,t);
}
if(r-l+1>n)return 0ll;
for(ri i=-l;i<n-r;++i){
for(ri j=0;j<n;++j)val[j]=-1;
st=stat=0;
char ch;
bool ff=1;
for(ri cur=i,j=0,up=upd.size();j<up;++j){
ch=upd[j];
switch(ch){
case '<':--cur;break;
case '>':++cur;break;
case '0':val[cur]=0,stat|=1ll<<cur;break;
case '1':val[cur]=1,stat|=1ll<<cur;break;
}
if(cur<0||cur==n){ff=0;break;}
bool fff=1;
for(ri j=0;j<n;++j)if(~val[j]&&(val[j]!=(To[j]-'0'))){fff=0;break;}
if(fff)st=stat;
}
if(ff&&S.query(st))sta.push_back(st);
}
return sta.size()?dfs(0,(1ll<<n)-1,0):0ll;
}
};