• Codeforces Round 901 (Div. 1) B. Jellyfish and Math(思维题/bfs)


    题目

    t(t<=1e5)组样例,每次给出a,b,c,d,m(0<=a,b,c,d,m<2的30次方)

    初始时,(x,y)=(a,b),每次操作,你可以执行以下四种操作之一

    ①x=x&y,&为与

    ②x=x|y,|为或

    ③y=x^y,^为异或

    ④y=y^m,^为异或

    求将(x,y)=(c,d)的最小操作数,如果无法实现,输出-1

    思路来源

    乱搞AC & tanao学弟

    题解

    按位考虑每一位时,有如下转移图,

    注意到,将m也考虑进去,会构成一个三元组,只有(0,0,0)到(1,1,1)八种可能

    30位里只有这8种可能,由于每次操作相同的可能的转移是一样的,

    所以,如果相同的(x>>i&1,y>>i&1,w>>&1)对应的(c>>i&1,d>>i&1)不同时,直接无解

    然后,可以只留8位,将8位标号id=0-7

    每个标号id都有出现和没出现两种情况,一共2的8次方,256种情况

    所以,可以对于第i(0<=i<256)情况预处理,

    初始的(a,b)和i是对应的,转化的(c,d)也都在[0,256)之间

    最多有256种情况*256*256种(c,d)值,每次转移有四种情况

    预处理之后,对于1e5组询问,O(1)回答即可

    代码中用的是数组记忆化,和预处理的效果是等价的

    复杂度O(256*256*256*4+1e5)

    代码

    1. #include
    2. // #include
    3. // #include
    4. // #include
    5. // #include
    6. using namespace std;
    7. #define rep(i,a,b) for(int i=(a);i<=(b);++i)
    8. #define per(i,a,b) for(int i=(a);i>=(b);--i)
    9. typedef long long ll;
    10. typedef double db;
    11. typedef pair<int,int> P;
    12. #define fi first
    13. #define se second
    14. #define dbg(x) cerr<<(#x)<<":"<" ";
    15. #define dbg2(x) cerr<<(#x)<<":"<
    16. #define SZ(a) (int)(a.size())
    17. #define sci(a) scanf("%d",&(a))
    18. #define pb push_back
    19. #define pt(a) printf("%d",a);
    20. #define pte(a) printf("%d\n",a)
    21. #define ptlle(a) printf("%lld\n",a)
    22. #define debug(...) fprintf(stderr, __VA_ARGS__)
    23. //std::mt19937_64 gen(std::chrono::system_clock::now().time_since_epoch().count());
    24. //ll get(ll l, ll r) { std::uniform_int_distribution dist(l, r); return dist(gen); }
    25. const int N=1e5+10,M=256,INF=0x3f3f3f3f;
    26. int t,a,b,c,d,m,dp[M][M*M];
    27. int f(int x,int y,int z){
    28. return x*4+2*y+z;
    29. }
    30. int g(int x,int y){
    31. return x*256+y;
    32. }
    33. int sol(){
    34. map<int,array<int,2>>p;
    35. rep(i,0,30){
    36. int u=a>>i&1,v=b>>i&1,w=m>>i&1,x=c>>i&1,y=d>>i&1,z=f(u,v,w);
    37. if(p.count(z)){
    38. if(p[z][0]!=x || p[z][1]!=y)return -1;
    39. }
    40. else{
    41. p[z]={x,y};
    42. }
    43. }
    44. int h=0,na=0,nb=0,nc=0,nd=0,nm=0;
    45. rep(i,0,7){
    46. if(p.count(i)){
    47. int u=i>>2&1,v=i>>1&1,w=i&1;
    48. h|=1<
    49. nc=nc<<1|p[i][0],nd=nd<<1|p[i][1];
    50. //printf("i:%d u:%d v:%d w:%d x:%d y:%d\n",i,u,v,w,p[i][0],p[i][1]);
    51. na=na<<1|u,nb=nb<<1|v,nm=nm<<1|w;
    52. }
    53. }
    54. int s=g(na,nb),e=g(nc,nd);
    55. if(dp[h][s]==0){
    56. return dp[h][e];
    57. }
    58. //printf("h:%d na:%d nb:%d nc:%d nd:%d\n",h,na,nb,nc,nd);
    59. dp[h][s]=0;
    60. queue<int>q;
    61. q.push(s);
    62. while(!q.empty()){
    63. int z=q.front();q.pop();
    64. int x=z/M,y=z%M;
    65. //if(x==nc && y==nd)return dp[z];
    66. vectorint,2>> nex={{x&y,y},{x|y,y},{x,x^y},{x,y^nm}};
    67. for(auto &w:nex){
    68. int nz=g(w[0],w[1]);
    69. if(dp[h][nz]<0){
    70. dp[h][nz]=dp[h][z]+1;
    71. q.push(nz);
    72. }
    73. }
    74. }
    75. return dp[h][e];
    76. }
    77. int main(){
    78. // freopen("qiwang.in","r",stdin);
    79. // freopen("qiwang.out","w",stdout);
    80. memset(dp,-1,sizeof dp);
    81. sci(t);
    82. while(t--){
    83. sci(a),sci(b),sci(c),sci(d),sci(m);
    84. printf("%d\n",sol());
    85. }
    86. return 0;
    87. }

  • 相关阅读:
    【Hadoop---13】MapReduce:Shuffle『Partitioner | Combiner』
    在linux上做移动开发必须知道这五个
    设计模式选择题答案
    《大厂高并发分布式锁从入门到实战》之第1讲分布式锁背景介绍及jvm锁和数据库锁
    Win10 CMD命令大全 命令提示符常用命令有哪些
    Docker镜像安全深度扫描
    车载软件架构——基础软件供应商&开发工具链(二)
    (仿牛客社区项目)Java开发笔记7.7:生成长图
    FFmpeg 参数
    vue3-admin商品管理后台项目(后台布局layout布局开发二)
  • 原文地址:https://blog.csdn.net/Code92007/article/details/133499832