[ARC145E] Adjacent XOR 题解

推荐在 cnblogs 上阅读。

[ARC145E] Adjacent XOR 题解

这道题真的是道神仙题,是那种考场想不出来、补题也补得十分艰难的题。可能我还是太菜了。

看了 APJ 大神的题解,琢磨很久才懂。为了帮助像我一样的同学,特地写一篇题解。

这是 2 月的第一篇题解、更是我的第一道黑题题解,谨纪念。

参考文献

  • [1] APJifengc,「解题报告」[ARC145E] Adjacent XOR

题意

给你 n n n 个整数 a 1 , a 2 , … , a n a_1,a_2,\dots,a_n a1,a2,,an,再给你 n n n 个整数 b 1 , b 2 , … , b n b_1,b_2,\dots,b_n b1,b2,,bn。通过执行以下操作,问你能不能操作 70000 70000 70000 次以内使得 a a a b b b 相同。

  • 操作:选择整数 k ∈ [ 1 , n ] k\in[1,n] k[1,n],进行 a i ← a i − 1 ⊕ a i a_i\leftarrow a_{i-1}\oplus a_i aiai1ai i ∈ [ 2 , k ] i\in[2,k] i[2,k] 的赋值操作。

数据范围: 2 ≤ n ≤ 1000 2\le n\le 1000 2n1000 0 ≤ a i , b i < 2 60 0\le a_i,b_i \lt 2^{60} 0ai,bi<260

Solution

转化目标

题意清晰,就是告诉你要构造方案。

由于每一次操作都是 a i ← a i − 1 ⊕ a i a_i\leftarrow a_{i-1}\oplus a_i aiai1ai,这个及其难下手。不妨反过来,从 b b b 入手。

在此之前,先琢磨透这个在 a a a 上做手脚的操作,到底是个啥?

其实一次操作,钦定 k k k 以后,就是去把每一个在 [ 2 , k ] [2,k] [2,k] a i a_i ai 都赋值为原 a a a 数组下标从 1 ∼ i − 1 1\sim i-1 1i1 的异或和。

而我们对 a i a_i ai 做手脚,是因为我们期望得到 b i b_i bi。这个对 a a a 数组的操作,每次都依靠前缀。

形式化地,这样:

b 1 = a 1 ′ = a 1 b 2 = a 2 ′ = a 1 ⊕ a 2 b 3 = a 3 ′ = a 1 ⊕ a 2 ⊕ a 3 … b i = a i ′ = ⊕ j = 1 i a j b_1=a'_1=a_1\\b_2=a'_2=a_1\oplus a_2\\b_3=a'_3=a_1\oplus a_2\oplus a_3\\\dots\\b_i=a'_i=\oplus_{j=1}^i a_j b1=a1=a1b2=a2=a1a2b3=a3=a1a2a3bi=ai=j=1iaj

现在考虑从 b b b 入手,从而推出 a a a。那么题意变为:

选择 k ∈ [ 1 , n ] k\in[1,n] k[1,n],进行 b i = ⊕ j = 1 i b j b_i=\oplus_{j=1}^i b_j bi=j=1ibj i ∈ [ 1 , k ] i\in[1,k] i[1,k] 的赋值操作。

为什么这样得到的 b i b_i bi 会等于 a i a_i ai 呢?展开一下就明白了:

b 1 ′ = b 1 b 2 ′ = b 1 ′ ⊕ b 2 b 3 ′ = b 1 ′ ⊕ b 2 ′ ⊕ b 3 b'_1=b_1\\b'_2=b'_1\oplus b_2\\b'_3=b'_1\oplus b'_2\oplus b_3 b1=b1b2=b1b2b3=b1b2b3

如果一项一项带入,就会发现 b i ′ = b i − 1 ⊕ b i b'_i=b_{i-1}\oplus b_i bi=bi1bi。又把 b i b_i bi a i a_i ai 表示,可以得到 b i ′ = ( a 1 ⊕ ⋯ ⊕ a i − 1 ) ⊕ ( a 1 ⊕ ⋯ ⊕ a i ) = a i b'_i=(a_1\oplus\dots\oplus a_{i-1})\oplus (a_1\oplus \dots \oplus a_i)=a_i bi=(a1ai1)(a1ai)=ai

至此,题意与解题目标发生了转化、也更加清晰。

能否构造

观察一手数据范围,可以跑 n log ⁡ b n\log b nlogb。考虑对于每个 i i i,就用 O ( log ⁡ b ) O(\log b) O(logb) 构造出一个 a i a_i ai。这里为了防止前缀和影响已更新好的数,我们选择倒着构造。

先判断能否构造,不难想到,可以构造的充要条件是:每一个 a i a_i ai 都可以由 b [ 1 , i − 1 ] b_{[1,i-1]} b[1,i1] 中的若干数与 b i b_i bi 异或得到。

构造开始

这个 b b b 数组,不是个善茬,想不到怎么很好处理。思考一下 b b b 数组需要做的操作,都是它的线性基可以处理的(其实看到异或问题,多多少少要想到一点线性基)。

我们把基底按先后加入顺序标号,来表示 b b b 的每一个数。此刻来考虑这个新数组 c c c

我们想从 a n ∼ a 1 a_n\sim a_1 ana1 进行构造,如果我们此时构造 a i a_i ai,那么我们不能动 a k a_k ak k ∈ [ i + 1 , n ] k\in[i+1,n] k[i+1,n];否则就打乱了。

所以,当我们改变到第 i i i 位的时候,只能对 k = i k=i k=i 进行操作: b i ← ⊕ j = 1 i b j b_i\leftarrow \oplus_{j=1}^ib_j bij=1ibj。实际上,就是构造异或和等于 a i a_i ai

我们按加入的先后顺序标号,所以当第 i i i 位最早在 p o s i pos_i posi 出现时,在 [ 1 , p o s i − 1 ] [1,pos_i-1] [1,posi1] i i i 这一位都为零。这个很显然。

那得知这个有什么用呢?我们可以通过这个将前缀异或和进行某一位的翻转。既然 p o s i pos_i posi 是第一次出现 i i i,那如果我对 k = p o s i + 1 k=pos_i+1 k=posi+1 进行操作,只有 b p o s i + 1 b_{pos_i+1} bposi+1 的异或和多了 i i i 这一位,总异或和这一位也就可以翻转了。

也是从大到小考虑, p o s i pos_i posi 递减,不会影响之前的数。

构造总结

那现在构造方法就很明了了:

  1. 从大到小枚举 i i i,计算当前异或和。
  2. 当异或和与 a i a_i ai (重标号后的)某一位不一样,就对那一位进行翻转操作。
  3. 最后对 k = m k=m k=m 进行操作,即可得出 a m a_m am
  4. 重复 n n n 遍,最后把操作序列翻转,就是从 a a a b b b 的操作了。

代码

code

#include <bits/stdc++.h>
using namespace std;

#define int long long

const int MAXN = 1e3 + 5;

int n;
int a[MAXN], b[MAXN], c[MAXN];
int pos[64];
vector<int> ans;

struct XXJ {
    int d[64];  // 基底
    int id[64], tot;
    void Clear() {
        memset(d, 0, sizeof(d));
        memset(id, 0, sizeof(id));
        tot = 0;
    }
    bool Count(int x) {
        for (int i = 59; ~i; i--)
            if (x >> i & 1) {
                if (d[i] == 0)
                    return 0;
                x ^= d[i];
            }
        return 1;
    }
    int Insert(int x) {
        int res = 0;
        for (int i = 60; ~i; i--)
            if (x >> i & 1) {
                if (d[i] == 0) {
                    d[i] = x;
                    id[i] = tot++;
                    return res | (1ll << id[i]);
                }
                res |= (1ll << id[i]);
                x ^= d[i];
            }
        return res;
    }
} X;

void work(int x) {
    ans.push_back(x);
    for (int i = 1; i <= x; i++) {
        b[i] ^= b[i - 1];
        c[i] ^= c[i - 1];
    }
}

signed main() {
    scanf("%lld", &n);
    for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
    for (int i = 1; i <= n; i++) scanf("%lld", &b[i]);

    for (int i = 1; i <= n; i++) {
        if (X.Count(a[i] ^ b[i]) == 0)
            return puts("No"), 0;
        X.Insert(b[i]);
    }

    for (int i = n; i; i--) {
        X.Clear();
        for (int j = 1; j <= i; j++) {
            bool flg = X.Count(b[j]);
            c[j] = X.Insert(b[j]);
            if (flg == 0)
                pos[__lg(c[j])] = j;
        }
        int tmp = X.Insert(a[i]);
        for (int j = X.tot; ~j; j--) {
            int sum = 0;
            for (int k = 1; k <= i; k++) sum ^= c[k];
            if ((sum >> j & 1) != (tmp >> j & 1))
                work(pos[j] + 1);
        }
        work(i);
    }

    reverse(ans.begin(), ans.end());
    printf("Yes\n%lld\n", (int)ans.size());
    for (int i : ans) printf("%lld ", i);

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/364393.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Kafka常见生产问题详解

目录 生产环境常见问题分析 消息零丢失方案 1、生产者发消息到Broker不丢失 2、Broker端保存消息不丢失 3、消费者端防止异步处理丢失消息 消息积压如何处理 如何保证消息顺序 ​问题一、如何保证Producer发到Partition上的消息是有序的 问题二&#xff1a;Partition中…

深入解剖指针篇(2)

目录 指针的使用 strlen的模拟实现 传值调用和传址调用 数组名的理解 使用指针访问数组 一维数组传参的本质 冒泡排序 个人主页&#xff08;找往期文章&#xff09;&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 指针的使用 strlen的模拟实现 库函数strlen的功能是求字符串…

面试经典 150 题 -- 矩阵 (总结)

总的链接 : 面试经典 150 题 - 学习计划 - 力扣&#xff08;LeetCode&#xff09;全球极客挚爱的技术成长平台 36 . 有效的数独 模拟 : 用数组模拟哈希表来判断对应的行&#xff0c;列和当前元素所在的3*3方格中是否重复出现&#xff0c;是的话&#xff0c;直接return false…

基于C/C++的MFC的IDC_MFCEDITBROWSE2控件不显示ico问题记录

打开资源文件 *.rc文件 &#xff0c;在最上方添加 #if !defined(_AFXDLL) #include "afxribbon.rc" // MFC ribbon and control bar resources #endif 如下图所示&#xff1a;

【IC设计】Windows下基于IDEA的Chisel环境安装教程(图文并茂)

Chisel环境安装教程 第一步 安装jdk&#xff0c;配置环境变量第二步 安装sbt&#xff0c;不用配置环境变量第三步 安装idea社区版第四步 离线安装scala的idea插件第五步 配置sbt换源1.切换目录2.创建repositories文件3.配置sbtconfig.txt文件 第六步 使用chisel-tutorial工程运…

亚信安慧的AntDB数据库:稳定可靠的保障

亚信安慧AntDB数据库在运营商自主可控替换项目中的成功应用&#xff0c;具有极其重要的意义。该数据库的落地&#xff0c;不仅为这一项目注入了强大的支持力量&#xff0c;还在更大程度上提升了整体的运营效能。作为一种高效可靠的数据库解决方案&#xff0c;AntDB引入了先进的…

如何通过CVE漏洞编码找到对应的CVE漏洞详情及源码修改地址

背景&#xff1a; 最近正在使用docker进行一些cve漏洞的复现&#xff0c;有时候就要通过CVE的漏洞编码&#xff0c;找到对应的漏洞详情&#xff0c;以及漏洞的源码修改 以我上一篇文章的CVE-2020-17518编码为例 Apache Flink文件上Apache Flink文件上 方法&#xff1a; 通…

Mobileye CES 2024 自动驾驶新技术新方向

Mobileye亮相2024年国际消费类电子产品展览会推出什么自动驾驶新技术? Mobileye再次亮相CES&#xff0c;展示了我们的最新技术&#xff0c;并推出了Mobileye DXP--我们全新的驾驶体验平台。 与往年一样&#xff0c;Mobileye是拉斯维加斯展会现场的一大亮点&#xff0c;让参观…

bank conflict

前置知识&#xff1a; shared memory 被分成 32 个 bank一个 warp 32 个线程每个 bank 4 byte如果同一 warp 中不同线程访问同一 bank 的不同地址则发生 bank conflict 请注意需要是一个 warp 中的不同线程&#xff01;如果一个线程访问 shared memory 的两个元素&#xff0c;…

win11安装MySql5.7

1、下载 打开下载链接&#xff1a;MySQL :: Download MySQL Installer 2、安装 2.1、安装界面 2.2、选择自定义安装 2.3、根据自己系统的位数进行选择是X64还是X86 2.4、选择安装路径 2.5、继续下一步 2.6、选择服务器专用&#xff0c;端口是3306 2.7、设置密码 2.8、设置服…

数学建模 - 线性规划入门:Gurobi + python

在工程管理、经济管理、科学研究、军事作战训练及日常生产生活等众多领域中&#xff0c;人们常常会遇到各种优化问题。例如&#xff0c;在生产经营中&#xff0c;我们总是希望制定最优的生产计划&#xff0c;充分利用已有的人力、物力资源&#xff0c;获得最大的经济效益&#…

代码随想录 Leetcode77.组合

题目&#xff1a; 代码&#xff08;首刷看解析 2024年2月1日&#xff09;&#xff1a; class Solution { public:vector<vector<int>> res;vector<int> path;void backtracing(int n, int k, int startIndex) {if (path.size() k) {res.push_back(path);re…

【Linux C | I/O模型】Unix / Linux系统的5种IO模型 | 图文详解

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

嵌入式学习 Day16

一. 共用体 形式&#xff1a; union 共用体名 { 成员列表; //各个变量 }; //表示定义一个共用体类型 注意&#xff1a; 1.共用体 初始化 --- 只能给一个值&#xff0c;默认是给到第一个成员变量的 2.共用体成员变量 共用体用的数据最终存储的 --…

了解Ansible自动化运维工具及模块的使用

一、Ansible的相关知识 1.1 Ansible工具的了解 Ansible是一个基于Python开发的配置管理和应用部署工具&#xff0c;现在也在自动化管理领域大放异彩。它融合了众多老牌运维工具的优点&#xff0c;Pubbet和Saltstack能实现的功能&#xff0c;Ansible基本上都可以实现。Ansible…

aspose-words基础功能演示

我们在Aspose.Words中使用术语“渲染”来描述将文档转换为文件格式或分页或具有页面概念的介质的过程。我们正在讨论将文档呈现为页面。下图显示了 Aspose.Words 中的渲染情况。 Aspose.Words 的渲染功能使您能够执行以下操作&#xff1a; 将文档或选定页面转换为 PDF、XPS、H…

gitlab操作手册

git操作篇 1. 项目克隆 git clone gitgitlab.test.cn:pro/project1.git2. 项目的提交 注&#xff1a;如果要查看文件的状态可以用git status命令&#xff1a; 如上图所示&#xff0c;文件已经修改了。 3. 项目的推送 git push origin feature/test01注&#xff1a;如果要查…

【遥感入门系列】遥感分类技术之遥感解译

遥感的最终成果之一就是从遥感图像上获取信息&#xff0c;遥感分类是获取信息的重要手段。同时遥感图像分类也是目前遥感技术中的热点研究方向&#xff0c;每年都有新的分类方法推出。 本小节主要内容&#xff1a; 遥感分类基本概念常见遥感分类方法 1 遥感分类概述 遥感图…

【Qt】Json在Qt中的使用

Json JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;广泛用于互联网应用程序之间的数据传输。JSON基于JavaScript中的对象语法&#xff0c;但它是独立于语言的&#xff0c;因此在许多编程语言中都有对JSON的解析和生成支持。…

C++ 音视频流媒体浅谈

C流媒体开发 今天就浅浅聊一下C流媒体开发 流媒体开发中最常见的是FFmpeg&#xff08;编解码器&#xff09; 业务逻辑主要是播放器了&#xff08;如腾旭视频 爱奇艺等等&#xff09; FFmpeg是一个开源的音视频处理工具集&#xff0c;可以用于处理、转换和流媒体传输音视频…