題解 P3943 星空
阿新 • • 發佈:2021-06-29
題解
一道思維量巨大的題,很燒腦
考慮異或差分,設 \(d_i=a_i\;\;xor\;\;a_{i-1}\),那麼對於翻轉 \(a_i\sim a_j\) 就相當於 \(b_i\) 和 \(b_{j+1}\) 異或 \(1\)
那麼我們最後要求的異或序列就全是 \(0\),那麼想辦法消去 \(1\),考慮狀壓
因為我們只想消去 \(1\),所以我們只需考慮異或為 \(1\) 的位置,而這最多有 \(2k\) 位,所以我們對這狀壓。
那麼我們考慮由 \(i\) 位異或到 \(j\) 位需要多少步,這個通過 \(bfs\) 來解決。
技巧:我們可以在列舉狀態時,對每個狀態只轉移最低位,因為每個狀態都會被轉移到。
這樣複雜度為 \(\mathcal O(2knm+2k×2^{2k})\)
Code:
#include<bits/stdc++.h> #define ri register signed #define p(i) ++i using namespace std; namespace IO{ char buf[1<<21],*p1=buf,*p2=buf; #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++ template<typename T>inline void read(T &x) { ri f=1;x=0;char ch=gc(); while(ch<'0'||ch>'9') {if (ch=='-') f=0;ch=gc();} while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=gc();} x=f?x:-x; } } using IO::read; namespace nanfeng{ #define lowbit(x) ((x)&-(x)) #define cmax(x,y) ((x)>(y)?(x):(y)) #define cmin(x,y) ((x)>(y)?(y):(x)) #define FI FILE *IN #define FO FILE *OUT static const int N=4e4+7,K=18; int dis[K][K],tdis[N],vis[N],b[K<<2],a[K],que[N],lg[1<<K],f[1<<K],tot,n,k,m; void bfs(int x,int id) { memset(tdis,0x3f,sizeof(tdis)); ri hd=1,tl=0; tdis[que[p(tl)]=x]=0; while(hd<=tl) { x=que[hd++]; for (ri i(1);i<=m;p(i)) { if (x-b[i]>0&&tdis[x-b[i]]>tdis[x]+1) tdis[x-b[i]]=tdis[x]+1,que[p(tl)]=x-b[i]; if (x+b[i]<=n+1&&tdis[x+b[i]]>tdis[x]+1) tdis[x+b[i]]=tdis[x]+1,que[p(tl)]=x+b[i]; } } for (ri i(1);i<=tot;p(i)) dis[id][i]=tdis[a[i]]; } inline int main() { // FI=freopen("nanfeng.in","r",stdin); // FO=freopen("nanfeng.out","w",stdout); read(n),read(k),read(m); for (ri i(1),x;i<=k;p(i)) read(x),vis[x]^=1,vis[x+1]^=1; for (ri i(1);i<=m;p(i)) read(b[i]); for (ri i(1);i<=n+1;p(i)) if (vis[i]) a[p(tot)]=i; for (ri i(1);i<=tot;p(i)) bfs(a[i],i); int S=(1<<tot)-1; for (ri i(2);i<=S;p(i)) lg[i]=lg[i>>1]+1; memset(f,0x3f,sizeof(f)); f[S]=0; for (ri i(S);i;--i) { int low=lg[lowbit(i)],bs=i^(1<<low); for (ri j(low+1);j<tot;p(j)) { if (!(i&(1<<j))) continue; int aim=bs^(1<<j); f[aim]=cmin(f[aim],f[i]+dis[low+1][j+1]); } } printf("%d\n",f[0]); return 0; } } int main() {return nanfeng::main();}