牛客题解 | 异或

news/2025/3/5 11:59:37/文章来源:https://www.cnblogs.com/wc529065/p/18752340

题目

题目链接

解题思路

给定 \(n\) 个整数和一个整数 \(m\),要求计算所有可能的两两异或结果中大于 \(m\) 的数量。可以使用字典树(Trie)来高效地存储和查询异或结果。

  1. 字典树构建:将每个数字的二进制表示插入字典树中。
  2. 查询异或结果:对于每个数字,查找已有数字中与其异或大于 \(m\) 的数量。
  3. 统计结果:在查找过程中,统计符合条件的异或对的数量。

关键点

  • 使用字典树存储二进制位,便于快速查找。
  • 通过位运算判断异或结果是否大于 \(m\)
  • 采用贪心策略,优先选择能使异或结果更大的路径。

代码

#include <bits/stdc++.h>
using namespace std;
using i64 = long long;const int N = 1e5 + 1;
int idx = 0;
int son[31 * N][2];  // 字典树节点
int num[31 * N];     // 节点计数int find(int x, int m) {int p = 0;int ans = 0;for (int i = 25; i >= 0; i--) {int bit = (x >> i) & 1;int mbit = (m >> i) & 1;if (mbit == 0) {// m的当前位是0,可以取更大的值if (son[p][1 - bit]) {ans += num[son[p][1 - bit]];}if (son[p][bit]) p = son[p][bit];else break;} else {// m的当前位是1,必须取更大的值if (son[p][1 - bit]) p = son[p][1 - bit];else break;}}return ans;
}void insert(int x) {int p = 0;for (int i = 25; i >= 0; i--) {int u = (x >> i & 1);if (!son[p][u]) {son[p][u] = ++idx;}p = son[p][u];num[p]++;}
}void solve() {int n, m;cin >> n >> m;i64 ans = 0;for (int i = 0; i < n; i++) {int x;cin >> x;ans += find(x, m);  // 先查找insert(x);          // 再插入}cout << ans;
}int main() {ios::sync_with_stdio(false);cin.tie(nullptr);solve();return 0;
}
import java.util.*;public class Main {static final int N = 100001;static int idx = 0;static int[][] son = new int[31 * N][2];static int[] num = new int[31 * N];static int find(int x, int m) {int p = 0;int ans = 0;for (int i = 25; i >= 0; i--) {int bit = (x >> i) & 1;int mbit = (m >> i) & 1;if (mbit == 0) {// m的当前位是0,可以取更大的值if (son[p][1 - bit] != 0) {ans += num[son[p][1 - bit]];}if (son[p][bit] != 0) p = son[p][bit];else break;} else {// m的当前位是1,必须取更大的值if (son[p][1 - bit] != 0) p = son[p][1 - bit];else break;}}return ans;}static void insert(int x) {int p = 0;for (int i = 25; i >= 0; i--) {int u = (x >> i & 1);if (son[p][u] == 0) {son[p][u] = ++idx;}p = son[p][u];num[p]++;}}public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();int m = sc.nextInt();long ans = 0;for (int i = 0; i < n; i++) {int x = sc.nextInt();ans += find(x, m);insert(x);}System.out.println(ans);sc.close();}
}
class TrieNode:def __init__(self):self.children = [None, None]  # 0和1的子节点self.count = 0  # 该节点的计数class Trie:def __init__(self):self.root = TrieNode()self.idx = 0  # 节点索引def insert(self, x):p = self.rootfor i in range(25, -1, -1):  # 从高位到低位bit = (x >> i) & 1if p.children[bit] is None:p.children[bit] = TrieNode()p = p.children[bit]p.count += 1  # 更新节点计数def find(self, x, m):p = self.rootans = 0for i in range(25, -1, -1):  # 从高位到低位bit = (x >> i) & 1mbit = (m >> i) & 1if mbit == 0:# m的当前位是0,可以取更大的值if p.children[1 - bit] is not None:ans += p.children[1 - bit].countif p.children[bit] is not None:p = p.children[bit]else:breakelse:# m的当前位是1,必须取更大的值if p.children[1 - bit] is not None:p = p.children[1 - bit]else:breakreturn ansdef main():import sysinput = sys.stdin.readdata = input().split()n = int(data[0])m = int(data[1])trie = Trie()ans = 0for i in range(n):x = int(data[i + 2])  # 从第三个元素开始读取数字ans += trie.find(x, m)  # 先查找trie.insert(x)          # 再插入print(ans)if __name__ == "__main__":main()

算法及复杂度

  • 算法:字典树(Trie)+ 位运算
  • 时间复杂度:\(\mathcal{O}(n * 26)\),其中 \(n\) 是数组长度
  • 空间复杂度:\(\mathcal{O}(31 * n)\),用于存储字典树节点

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

牛客题解 | 平方串

牛客题库题解题目 题目链接 题解 题目难度:中等 知识点:LCS(最长公共子序列问题),动态规划 分析: 本题实际是要找出s的最长子序列,看到这个问题就应该想到利用动态规划去解决。一般是找s1、s2两个字符串中的最长子序列,那么该题中就可以遍历s,以每个字符位置作为分割点…

车身域控制器BDCU

集成化是整车降本最重要的手段,域控和线束的深度融合是提升整车集成度的关键。车身域控制器作为汽车域控制器之一,在功能集成、系统优化和技术创新方面取得了显著进展。经纬恒润自主研发的车身域控制器(BDCU),能够兼容传统BCM功能,同时集成空调算法、门控逻辑、胎压监控等…

随记-NGNIX关于反向代理8080 和 8081

​ 在\conf\nginx.conf中有一段代码这里解释是: 在这个 Nginx 配置中,8080 和 8081 是两个不同的端口,分别用于不同的用途。它们的关系如下:8080 端口 作用: Nginx 监听 8080 端口,作为前端请求的入口。 功能: 处理静态资源请求(如前端页面)。 将 /api 开头的请求转发到…

RLChina2024 | 汪军 LLM and AI Agents: A Roadmap and Vision towards AGI

本文记录此次报告的key point(个人向) llm时代的几点difficulityInference-time computation scallingOpenAI o1 利用RL来显式整合inference期间推理的step(inference-time computation) (从predicte next-token范式到RL解决问题范式)predict next token是监督学习,受限于…

若依开发微信小程序遇到的问题一

如上所述,该错误是由于Spring在创建familyMemberController时,无法满足familyMemberService的依赖注入。进一步追踪发现,wechatServiceImpl中的wechat.appId配置项未正确配置,导致依赖注入失败。 分析原因可能是配置文件缺失或错误:wechat.appId在配置文件中未定义或拼写错…

AI工具链接汇总

1、chatgpt4 https://www.chatgp4.com/gpt功能应用场景:智能文案生成:GPT网页版智能平台具备强大的自然语言处理能力,能够根据用户输入的关键词或提示,生成高质量的文章、广告文案、营销邮件等。无论是文章创作、内容编辑,还是社交媒体上的推文撰写,都能高效完成,极大地…

linux另类实现matlab编辑器的vim模式

使用matlab编程练习中,发现matlab的自带的编辑器也不错,主要是分节运行非常方便,但是没有vim模式有点难受。经过摸索,变相实现了matlab中的编辑器的vim模式。安装好linux下matlab 2024a,其他版本也无所谓,安装好vim,我的是最新版本。左边显示器垂直放置,右边显示器水平…

在Unity转微信小游戏下,如何用Worker实现多线程

1)在Unity转微信小游戏下,如何用Worker实现多线程2)Unity的jslib库和微信小游戏的game.js如何互相调用函数或者通信3)如何在Unity中实现资源的深度复制这是第422篇UWA技术知识分享的推送,精选了UWA社区的热门话题,涵盖了UWA问答、社区帖子等技术知识点,助力大家更全面地…

YASKAWA喷涂机器人维修的常见问题

一、安川机器人示教器维修步骤详解 - 检查电源供应:确保电源供应正常,检查电源模块是否有短路或其他损坏。 - 检查连接:检查示教器与其他组件的连接是否牢固,包括电缆、插头等。 - 检查电路板:检查示教器电路板上的电子元件是否有明显的损坏,如烧焦、膨胀…

面试官:谈谈你对线程池拒绝策略的理解?

线程池的拒绝策略是指,当线程池无法承载更多任务时执行的行为。也就是当线程池的核心线程数、最大线程、任务队列都满的情况下,又来了新的任务时,线程池执行的行为被称之为线程池的拒绝策略。 线程池的执行流程如下:1.内置拒绝策略 在 Java 中,线程池内置了以下四种拒绝策…

ABB IRB1410弧焊机器人示教器维修

在现代工业生产中,ABB IRB1410弧焊机器人发挥着重要的作用。然而,如同所有设备一样,它也可能面临各种故障,这就需要进行有效的维修,尤其是示教器部分的维修,这关系到整个弧焊机器人的正常运行。一、ABB机器人维修的重要性ABB机器人在工业领域广泛应用,其维修工作至关重要…

开发HarmonyOS NEXT版五子棋游戏实战

大家好,我是 V 哥。首先要公布一个好消息,V 哥原创的《鸿蒙HarmonyOS NEXT 开发之路 卷1:ArkTS 语言篇》图书终于出版了,有正在学习鸿蒙的兄弟可以关注一下,写书真是磨人,耗时半年之久,感概一下,希望可以帮助到正在入门鸿蒙开发的小伙伴,一书在手 ArkTS无优。 今天要给…