orangejuice's blog
按ctrl会跳搜索,右上角选择day/night mode 似乎修好了搜索
测试中博客
做得我很迷
首先是可以把问题转化为,每次操作之后会让原序列的限制条件变为:不考虑某一些位置时合法
枚举每个开始位置,依次考虑每一个操作,如果有一个位置被改为不同,就是不合法的
对于每一个开始位置,能得到的的最优限制条件都是唯一的,因为只要是合法的,一定取最后一个合法的位置,才能尽可能多地覆盖一些位置
那么我们得到了$|goal|$个这样的限制条件$S_i$,设$n=|goal|$
直接计算肯定会算重,考虑一个简单的容斥
$\begin{aligned}Answer=\sum_{T\ne \empty}(-1)^{|T|+1}2^{|S_{T_1}\cap \cdots \cap S_{T_{|T|} }|}\end{aligned}$
就是枚举选择一个限制的集合,求出他们的并集
直接枚举复杂度当然是$O(2^{|n|})$,如果$\text{dfs}$枚举,当前状态为$0$时,可以直接返回答案
估计一下这个$\text{dfs}$的复杂度
设操作过程中指针左右移动的距离是$L$,那么最多存在$n-L$个合法的开始位置,每个状态最多包含$L$个$1$
很显然枚举的上限是$\min\{2^{n-L},2^{L} \}$,即受到开始位置的个数和可能出现的1个数的限制
当$n-L=L$时,复杂度达到上限是$O(2^{\frac{n} {2} })$
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| #include<bits/stdc++.h> using namespace std; typedef long long ll; #define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i) #define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)
set <ll> st; ll S[40]; int now[40],cnt; ll dfs(int p,ll State){ if(p==cnt+1) return (1ll<<__builtin_popcountll(State)); if(State==0) return 0; return dfs(p+1,State)-dfs(p+1,State&S[p]); }
class MapGuessing { public: long long countPatterns(string S, vector <string> code) { string C=""; for(string t:code) C+=t; int n=S.size(); st.clear(); rep(i,0,n-1) { int p=i,f=1; ll lst=0; rep(i,0,n-1) now[i]=0; for(char c:C) { if(c=='<') p--; if(c=='>') p++; if(c=='0') now[p]=1; if(c=='1') now[p]=2; if(p<0 || p>=n){ f=0; break; } int fl=1; ll T=0; rep(i,0,n-1) { if(!now[i]) continue; if(now[i]-1!=S[i]-'0'){ fl=0; break; } else T|=1ll<<i; } if(!fl) continue; lst=T; } if(!f) continue; st.insert(-lst); } cnt=0; for(ll x:st) { ll y=-x; int f=1; rep(i,1,cnt) if((::S[i]&y)==y){ f=0; break; } if(f) ::S[++cnt]=y; } ll ans=(1ll<<n)-dfs(1,(1ll<<n)-1); return ans; } };
|
本文代表个人观点,内容仅供参考。若有不恰当之处,望不吝赐教!