[lnsyoj2246/luoguCF979D]Kuro and GCD and XOR and SUM
题意
给定集合 ,初始为空,进行 次修改或查询操作:修改操作将 加入集合;查询操作给定 ,要求找到满足
的最小的 。
sol
集合、异或、可查可改,可以自然地想到 0/1-Trie。
我们假设 ,此时不需要考虑 的条件,这就是一个有上限的最大异或和问题。我们对每个点记录一个 ,表示经过这个点的最小值,这样,当找到一个点时,如果 ,就不能够进入这个点。
再来考虑 ,我们可以对于每一个可能的 值都建立一棵 Trie 树,这样,每次插入的时候, 地枚举所有约数代表的 Trie 树,在这些 Trie 树中都插入 。查询的时候直接查找第 棵树即可。
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <unordered_set>
using namespace std;
const int N = 50000005, K = 20;
int q;
int tr[N][2], minn[N], idx;
unordered_set<int> st;
void ins(int x, int p){
for (int c = K - 1; c >= 0; c -- ){
int u = (x >> c) & 1;
if (!tr[p][u]) tr[p][u] = ++ idx;
p = tr[p][u];
minn[p] = minn[p] ? min(minn[p], x) : x;
}
}
int query(int x, int s, int k){
int res = 0, p = k;
for (int c = K - 1; c >= 0; c -- ){
int u = ((x >> c) & 1) ^ 1;
int ne = tr[p][u], xne = tr[p][u ^ 1];
if (ne && minn[ne] <= s - x) res += u << c, p = ne;
else if (xne && minn[xne] <= s - x) res += (u ^ 1) << c, p = xne;
else return -1;
}
return res ? res : -1;
}
int main(){
idx = 100000;
scanf("%d", &q);
while (q -- ){
int op, x;
scanf("%d%d", &op, &x);
if (op == 1) {
if (st.find(x) == st.end()){
for (int i = 1; i * i <= x; i ++ ){
if (x % i) continue;
ins(x, i);
if (i * i != x) ins(x, x / i);
}
st.insert(x);
}
}
else {
int k, s;
scanf("%d%d", &k, &s);
if (x % k) puts("-1");
else printf("%d\n", query(x, s, k));
}
}
return 0;
}
分类:
题解 / 2024赛时
标签:
数据结构
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现