【学习笔记】[AGC061E] Increment or XOR

看着感觉很吓人 毕竟是 A G C AGC AGC E E E ,但是其实只要给一点提示这题还是很好着手的。

也仅仅是看着很好着手罢了。

看了一下官方题解,感觉比翻译的清晰多了。

直接讲做法了。数据删除 这道题的状态设计非常巧妙,设 ( k , s , f , m a s k ) (k,s,f,mask) (k,s,f,mask)表示一个子问题,包含这样的信息:

1.1 1.1 1.1 k k k表示只考虑末尾 k k k位,也就是后 k k k位的一个截断
1.2 1.2 1.2 s s s表示初始状态,其中 s = 0 s=0 s=0表示初始状态为 S S S s = 1 s=1 s=1表示初始状态全为 0 0 0 t t t表示目标状态,其中 t = 0 t=0 t=0表示目标状态为 T T T并且过程中不产生 k − 1 → k k-1\to k k1k的进位,也就是说进位操作只影响后 k k k位; t = 1 t=1 t=1表示有且仅发生一次恰好从 k − 1 → k k-1\to k k1k的进位,这句话也隐含了一些信息,我们后面再来说。
1.3 1.3 1.3 m a s k mask mask表示每个操作的次数的奇偶性。

定义 c o s t ( k , s , f , m a s k ) cost(k,s,f,mask) cost(k,s,f,mask)表示这个子问题的最小代价。

然后看转移。我们只考虑相邻层的转移,换句话说,我们只需要在让 [ 0 , k − 1 ] [0,k-1] [0,k1]位匹配的基础上让 k k k位匹配就好了。并且我们还有限制,进位有影响只能发生在 k − 1 → k k-1\to k k1k。这个转移刚开始令我非常费解,因为它的思路有一点奇怪:用小规模的问题去强行拼凑出大规模问题的解。

1.1 1.1 1.1 如果没有产生 k − 1 → k k-1\to k k1k的进位,那么我们根据 m a s k mask mask就能知道第 k k k位是否匹配,如果匹配那么 c o s t ( k , s , 0 , m a s k ) → c o s t ( k + 1 , s , 0 , m a s k ) cost(k,s,0,mask)\to cost(k+1,s,0,mask) cost(k,s,0,mask)cost(k+1,s,0,mask)。这里我要多解释一句,比如说 s = 1 s=1 s=1,那么就让 S k ← 0 S_k\gets 0 Sk0,再比较经过 m a s k mask mask掩码后是否与 T k T_k Tk匹配。

1.2 1.2 1.2 如果产生了 k − 1 → k k-1\to k k1k的进位,那么 一定 是经过了形如 ( k , s , 1 , m 0 ) (k,s,1,m_0) (k,s,1,m0) ( k , 1 , 1 , m 1 ) , . . . , ( k , 1 , f , m i ) (k,1,1,m_1),...,(k,1,f,m_i) (k,1,1,m1),...,(k,1,f,mi)的操作序列,最后转移到 ( k + 1 , s , f , ⨁ m i ) (k+1,s,f,\bigoplus m_i) (k+1,s,f,mi)。换句话说,先把 S k ← S k / 0 S_k\gets S_k/0 SkSk/0,然后进行若干次 k − 1 → k k-1\to k k1k的进位,但是都只影响了 [ 0 , k ] [0,k] [0,k]位;因为 [ 0 , k − 1 ] [0,k-1] [0,k1]位已经被还原了,就只要考虑 k k k位最后恰好匹配上即可。注意过程中要检验 k k k位的取值。这里还是要多解释一下,如果 f = 0 f=0 f=0那么限制要宽松一些,就是说最后那一段操作没有进位,就检查最后 k k k位是否匹配就好了;如果 f = 1 f=1 f=1那么最后一个操作是作了 k − 1 → k k-1\to k k1k的进位的,这个时候应该保证 k k k位是 1 1 1,才能继续进位,这样和状态才合得上。最后要说的就是除了最后一次操作,过程中每一次 k − 1 → k k-1\to k k1k进位的时候都要保证 k k k位是 0 0 0才行。

怎么转移不用我多说吧。直接在图上做就好了,因为边权都是非负的。

但是我们还是没有解释为什么只转移到这 4 4 4个特殊状态是对的。这似乎可以用一句万能的套话来说明:最优解一定包含在内。想了想发现确实如此。算了就当我没证吧。

总结一下,这道题还是花费了我相当长的时间,感觉过程中一些处理的细节想了很久才想清楚,总体而言这道题比看起来要棘手一些。

时间复杂度 O ( B 4 n ) O(B4^n) O(B4n)

代码写起来比较不适。细节贼多,建议写之前把细节想清楚。

#include<bits/stdc++.h> #define ll long long #define fi first #define se second #define pb push_back #define db double #define inf 0x3f3f3f3f3f3f3f3f using namespace std; int n,vis[1<<8][2][2]; ll S,T,A,nums[8],numsets[1<<8],costs[8],now[1<<8][2][2],now2[1<<8][2][2],nxt[1<<8][2][2]; void chmin(ll &x,ll y){x=min(x,y);} ll get(int s,int j){ if(j==0)return S^numsets[s]; return numsets[s]; } signed main(){ ios::sync_with_stdio(false); cin.tie(0),cout.tie(0); cin>>n>>S>>T>>A; for(int i=0;i<n;i++)cin>>nums[i]>>costs[i]; for(int s=0;s<1<<n;s++){ for(int i=0;i<n;i++){ if(s>>i&1)numsets[s]^=nums[i]; } } for(int s=0;s<1<<n;s++){ for(int i=0;i<2;i++){ for(int j=0;j<2;j++){ if(j==1)now[s][i][j]=A; for(int k=0;k<n;k++){ if(s>>k&1)now[s][i][j]+=costs[k]; } } } } for(int i=0;i<=40;i++){ memset(vis,0,sizeof vis); //fixed memset(nxt,0x3f,sizeof nxt); //fixed memset(now2,0x3f,sizeof now2); for(int s=0;s<1<<n;s++){ for(int j=0;j<2;j++){ if((get(s,j)>>i&1)==(T>>i&1)){ chmin(nxt[s][j][0],now[s][j][0]); } } } for(int s=0;s<1<<n;s++){ for(int j=0;j<2;j++){ if((get(s,j)>>i&1)==0){ chmin(now2[s][j][1],now[s][j][1]); } else{ chmin(nxt[s][j][1],now[s][j][1]); } } } //fixed while(1){ int ts=-1,tj=0; for(int s=0;s<1<<n;s++){ for(int j=0;j<2;j++){ if(!vis[s][j][1]&&now2[s][j][1]!=inf&&(ts==-1||now2[s][j][1]<now2[ts][tj][1])){ ts=s,tj=j; } } } if(ts==-1)break; assert(vis[ts][tj][1]==0); vis[ts][tj][1]=1; for(int s2=0;s2<1<<n;s2++){ for(int j=0;j<2;j++){ if(j==0){ if(((numsets[s2]>>i&1)^1)==(T>>i&1)){ chmin(nxt[ts^s2][tj][0],now2[ts][tj][1]+now[s2][1][0]); } } else{ if(((numsets[s2]>>i&1)^1)==0){ chmin(now2[ts^s2][tj][j],now2[ts][tj][1]+now[s2][1][1]); } else{ chmin(nxt[ts^s2][tj][j],now2[ts][tj][1]+now[s2][1][1]); } } } } } memcpy(now,nxt,sizeof nxt); } ll res=inf; for(int s=0;s<1<<n;s++){ res=min(res,now[s][0][0]); } if(res==inf)cout<<-1; else cout<<res; }

__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17529953.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(13)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示