挺巧妙的题
看起来无从下手
k很小,先不管
把最终需要亮的看做1,不需要的看做0
要把全0序列,变成有至多10个1的01序列
不妨考虑把01序列变回全0序列(这样容易思考)
区间取反?
差分变成两个单点取反!
特殊加入n+1位置,这样便于取反
首先,两个0取反一定不优,可以用01取反和11取反来得到相同的效果
01取反,等价于1走到0,11取反,等价于两个1消掉。
不断两个位置进行取反,一定是为了最后把两个1消掉!
也就是,其实是两个1的匹配!
1一共只有20个
最短路建图,f[i][j]表示i和j匹配的最小代价,也即最短路
一个问题是:不会影响其他位置的值吗?
发现这个最短路的边,除了起点终点,都恰好xor两次(虽然这样并不优)!不会影响其他的位置的值!
BFS求最短路
然后Dp即可
枚举和S的lowbit进行匹配的点
O(20*2^20)
#include<bits/stdc++.h> #define reg register int #define il inline #define fi first #define se second #define mk(a,b) make_pair(a,b) #define numb (ch^'0') #define pb push_back #define solid const auto & #define enter cout<<endl #define pii pair<int,int> using namespace std; typedef long long ll; template<class T>il void rd(T &x){ char ch;x=0;bool fl=false;while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true); for(x=numb;isdigit(ch=getchar());x=x*10+numb);(fl==true)&&(x=-x);} template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');} template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');} template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar(' ');} namespace Modulo{ const int mod=998244353; int ad(int x,int y){return (x+y)>=mod?x+y-mod:x+y;} void inc(int &x,int y){x=ad(x,y);} int mul(int x,int y){return (ll)x*y%mod;} void inc2(int &x,int y){x=mul(x,y);} int qm(int x,int y=mod-2){int ret=1;while(y){if(y&1) ret=mul(x,ret);x=mul(x,x);y>>=1;}return ret;} } //using namespace Modulo; namespace Miracle{ const int N=10000+5; const int M=105; const int K=22; const int inf=0x3f3f3f3f; int n,k,m; int pos[K],dis[N],cnt; int f[K][K]; int a[N],b[N]; int dp[(1<<20)+23]; int q[N],l,r; void bfs(int st){ memset(dis,0x3f,sizeof dis); dis[pos[st]]=0; l=1,r=0; q[++r]=pos[st]; while(l<=r){ int x=q[l++]; for(reg i=1;i<=m;++i){ int to=x+b[i]; if(to<=n+1&&dis[to]>dis[x]+1){ dis[to]=dis[x]+1; q[++r]=to; } to=x-b[i]; if(to>0&&dis[to]>dis[x]+1){ dis[to]=dis[x]+1; q[++r]=to; } } } for(reg i=1;i<=cnt;++i){ f[st][i]=dis[pos[i]]; } } int num(int p){ int sz=__builtin_ctz(p); return sz+1; } int main(){ rd(n);rd(k);rd(m); for(reg i=1;i<=k;++i){ int x;rd(x); a[x]=1; } for(reg i=1;i<=m;++i){ rd(b[i]); } for(reg i=n+1;i>=1;--i){ a[i]^=a[i-1]; if(a[i]==1) pos[++cnt]=i; } // prt(a,1,n+1); // prt(pos,1,cnt); for(reg i=1;i<=cnt;++i){ // cout<<" bfs i------------ "<<i<<endl; bfs(i); // prt(f[i],1,cnt); } memset(dp,0x3f,sizeof dp); dp[0]=0; for(reg s=1;s<(1<<cnt);++s){ int sz=__builtin_popcount(s); if((sz&1)) continue; // cout<<" ss "<<s<<endl; int t=s&(-s); for(reg tmp=s^t,p=tmp&(-tmp);tmp;tmp=tmp^p,p=tmp&(-tmp)){ // cout<<" t "<<t<<" num(t) "<<num(t)<<" p "<<p<<" num(p) "<<num(p)<<" fan "<<dp[s^t^p]<<endl; dp[s]=min(dp[s],dp[s^t^p]+f[num(t)][num(p)]); } } // prt(dp,0,(1<<cnt)-1); if(dp[(1<<cnt)-1]==inf){ puts("-1"); }else{ printf("%d ",dp[(1<<cnt)-1]); } return 0; } } signed main(){ Miracle::main(); return 0; } /* Author: *Miracle* */