大厂真题 / 百度
百度算法岗 2026-09-17
内容边界:该场笔试声明共有 20 道选择题,材料只展开了第 1 至第 5 题。本文收录这 5 道可核对的选择题和 2 道完整编程题,不补写缺失的第 6 至第 20 题,也不补充原文未披露的题目、样例、约束与字段。
本场考试概述
考试时间:2026年9月17日
考试岗位:算法岗
难度评级:简单偏中等
考点分析:
- 选择题:可恢复 5 道,涉及大模型工具调用、KV Cache 与推理部署、RAG 工程、并查集路径压缩与 SFT 数据质量。
- 第一题 区间异或和最小右端点:前缀异或 + 周期规律(难度简单)。
- 第二题 数位长度乘数位和最小值:枚举位数 + 数位贪心(难度中等)。
建议策略:
- 选择题里大模型工程场景占了近一半,选项常有一眼能排除的错误做法,按排除法走会快很多。
- 第一题不要逐个异或枚举,先推出 $0$ 到 $n$ 的异或和按 $n\bmod 4$ 循环的规律,候选答案只有 6 个。
- 第二题按位数从小到大试、从高位往低位贴着下界填;注意 $10^{16}$ 本身在区间内,$x=17$ 的答案是 $10^{16}$,中间结果要用 64 位整数保存。
选择题(可恢复 5 道)
1、Agent 需要调用两个工具:先查订单状态,再决定是否退款。更合理的链路是?
A. 两个工具共用无约束字符串参数并跳过状态字段
B. 模型产出结构化计划,系统校验订单状态后退款
C. 先执行退款工具,再让模型解释订单状态变化
D. 状态查询失败时按用户催促先退款再补查订单
答案:B
解析:退款是有副作用、不可撤销的操作,必须以查询到的订单状态为前置条件,由模型给出结构化调用计划、系统侧做校验后再执行。A 用无约束字符串参数且跳过状态字段,调用结果无法校验;C 先执行后解释,顺序颠倒;D 在查询失败时仍执行退款,等于绕过了前置校验。
2、长上下文推理的 KV Cache 随并发和序列长度快速占满显存。在不修改模型权重且要兼顾吞吐与时延的前提下,应优先怎么做?
A. 结合上下文上限、并发数以及分页和淘汰策略控制占用
B. 关闭缓存并在每个解码步重算全部历史 token 以降低延迟
C. 无限延长组批等待时间,用更大 batch 摊薄缓存占用
D. 为每个请求预留最大上下文长度的连续显存空间
答案:A
解析:KV Cache 的占用约与「并发数乘以序列长度」成正比,限制上下文上限与并发,再用分页管理消除碎片、配合淘汰策略,能在不动权重的前提下同时保住吞吐与时延。B 关闭缓存后每一步都要重算历史,延迟反而大幅上升;C 无限等待组批会让首 token 时延失控,更大的 batch 也占用更多缓存;D 按最大长度预留连续显存正是碎片和浪费的来源。
3、RAG 系统检索到了正确文档,但正确段落排序靠后,未进入注入上下文。更应优先优化什么?
A. 重排和上下文截取规则
B. 弱化文档版本字段
C. 把回答长度调到更短
D. 让模型绕过检索自由回答
答案:A
解析:召回已经命中,问题出在排序与截断:正确段落排名靠后被截掉了,应引入或调优重排模型,并调整进入上下文的条数与截取规则。B 与排序无关,还可能引入旧版本内容;C 调的是生成长度,不影响注入哪些段落;D 放弃检索只会加剧幻觉。
4、并查集的 parent 关系为 1→2、2→3、3→4、4→4。对 1 执行带路径压缩的 find 操作后,parent 关系会怎样变化?
A. 4 的父节点被改成 1 以保持链式结构
B. 1 和另一个未查询集合被合并到一起
C. 1、2、3 被重新编号为新的集合编号
D. 1、2、3 都更直接地指向根节点 4
答案:D
解析:查找从 1 沿 1→2→3→4 找到根 4,路径压缩会把沿途经过的 1、2、3 的 parent 都直接改成 4,链被压平,后续查询接近 $O(1)$。A 改动了根,破坏了集合代表元;B 是 union 的行为,查找不会合并集合;C 并查集不重新编号,集合代表始终是根 4。
5、SFT 数据中若同一指令存在多个互相矛盾的目标回答,最直接的风险是?
A. 奖励模型分数会替代 SFT 标签成为主要训练信号
B. 增加训练轮次后矛盾标签会稳定提升指令遵循能力
C. 偏好数据的胜负样本顺序会默认修正这些冲突
D. 监督信号冲突,使模型响应风格和事实边界不稳定
答案:D
解析:SFT 用交叉熵拟合目标回答,同一输入对应互相矛盾的标签时,模型只能学到它们的混合分布,表现为同类问题回答风格摇摆、事实口径前后不一。A、C 把 RLHF 阶段的奖励模型与偏好数据混进了 SFT,SFT 本身不涉及二者;B 多训几轮只会把冲突记得更牢,不会变好。
第 1 题:区间异或和最小右端点
题目描述
给定两个非负整数 $x$ 与 $z$,求满足
\[x\oplus(x+1)\oplus(x+2)\oplus\cdots\oplus y=z\]且 $y\ge x$ 的最小整数 $y$,其中 $\oplus$ 表示按位异或操作。若不存在这样的 $y$,输出 $-1$。
输入描述
输入两个整数 $x,z$,满足 $0\le x<2^{20}$,$0\le z<2^{20}$。
输出描述
如果不存在对应的 $y$,直接输出 $-1$;否则输出一个非负整数,表示最小的能使等式成立的 $y$。
样例 1
输入
1 4
输出
4
样例解释:$1\oplus2\oplus3\oplus4=4$,而 $y=1,2,3$ 时区间内所有整数的异或结果分别为 $1,3,0$,都不等于 $4$,所以最小的 $y$ 为 $4$。
思路分析
第一步:把区间异或拆成两个前缀异或。 记
\[F(n)=0\oplus1\oplus\cdots\oplus n,\qquad F(-1)=0\]由 $a\oplus a=0$,$F(y)\oplus F(x-1)$ 中下标小于 $x$ 的那些数两两抵消,剩下的恰好是区间 $[x,y]$ 的异或和。于是原等式等价于
\[F(y)=t,\qquad t=z\oplus F(x-1)\]而 $x=0$ 时 $F(-1)$ 取 $0$。
第二步:看懂前缀异或的周期。 连续四个数 $4k,4k+1,4k+2,4k+3$ 的高位完全相同,低两位取遍 $00,01,10,11$,异或结果为 $0$,所以前缀每满 $4$ 个数就清零一次,$F(n)$ 只由 $n\bmod 4$ 决定:
\[F(n)= \begin{cases} n, & n\bmod 4=0,\\ 1, & n\bmod 4=1,\\ n+1, & n\bmod 4=2,\\ 0, & n\bmod 4=3. \end{cases}\]第三步:把候选压到 6 个。 当 $F(y)$ 取常数值 $1$ 或 $0$ 时,满足 $F(y)=t$ 的 $y$ 每 $4$ 个数出现一次,而 $x,x+1,x+2,x+3$ 恰好覆盖一个完整的模 $4$ 周期,所以最小的那个若存在必定落在这四个数里。当 $F(y)$ 取 $y$ 或 $y+1$ 时,方程只有一个解,$y$ 只能是 $t$ 或 $t-1$。
第四步:实现。 先按上面的式子算出 $t$,再逐个检查 $x,x+1,x+2,x+3,t-1,t$ 这 6 个候选,保留同时满足 $y\ge x$ 与 $F(y)=t$ 的,取最小值;一个都不满足就说明无解。
正确性说明
前缀分解对任意 $y\ge x$ 都成立,所以「$F(y)=t$」与原等式完全等价。又因为 $F$ 按模 $4$ 只取上述四种形态:当 $F(y)$ 取常数 $1$ 或 $0$ 时,可行下标每 $4$ 个出现一次,其中最小的一个必定落在 $[x,x+3]$ 这段完整周期内;当 $F(y)$ 取 $y$ 或 $y+1$ 时,方程的解只能是 $y=t$ 或 $y=t-1$。因此 6 个候选覆盖了解的全部可能,代码筛掉不满足 $y\ge x$ 与 $F(y)=t$ 的候选取最小值,得到的就是最小的可行 $y$;候选全被筛掉时确实不存在可行解。
题解代码
import sys
input = sys.stdin.readline
# 前缀异或 F(n) = 0 ^ 1 ^ ... ^ n,按 n % 4 分成四种情况
def prefix_xor(n):
if n < 0:
# 空前缀的异或和为 0
return 0
r = n % 4
if r == 0:
return n
if r == 1:
return 1
if r == 2:
return n + 1
return 0
# 返回最小的 y >= x 使 x ^ (x+1) ^ ... ^ y == z,不存在返回 -1
def min_right(x, z):
# 区间异或 = F(y) ^ F(x-1),所以只要找 F(y) 等于 target 的下标
target = z ^ prefix_xor(x - 1)
# F(y) 取 1 或 0 时,y 每 4 个数出现一次,x..x+3 里必定有最小的那个;
# F(y) 取 y 或 y+1 时,y 只能是 target 或 target-1
best = -1
for y in (x, x + 1, x + 2, x + 3, target - 1, target):
if y >= x and prefix_xor(y) == target:
if best == -1 or y < best:
best = y
return best
def main():
x, z = map(int, input().split())
print(min_right(x, z))
main()
复杂度分析
时间复杂度:$O(1)$。只检查 6 个候选,每个候选按 $n\bmod 4$ 用常数时间算出前缀异或;朴素的逐个异或是 $O(y-x)$,而且在无解时根本没有终止条件。
空间复杂度:$O(1)$。只用到几个整型变量,与输入规模无关。
易错点
- $x=0$ 时要用 $F(-1)=0$,不能把 $F(x-1)$ 当成未定义。
- 候选必须先过滤 $y\ge x$,其中 $t-1$ 还可能是负数。
- 无解的情形确实存在:$t\bmod 4=2$ 时四个分支都取不到 $t$;$t\bmod 4=1$ 且 $t\ne1$ 时同理;$t\bmod 4=0$ 但 $t<x$ 时,唯一候选 $t$ 会被 $y\ge x$ 挡掉。
- 按位异或与十进制加法不同,不要写出越界的中间值去试算。
第 2 题:数位长度乘数位和最小值
题目描述
给定一个正整数 $x$。用 $\lvert a\rvert$ 表示十进制下整数 $a$ 的数位长度,用 $\operatorname{sum}(a)$ 表示 $a$ 的十进制数位和。
请在区间 $[1,10^{16}]$ 内,找到满足
\[\lvert a\rvert\cdot\operatorname{sum}(a)=x\]的最小整数 $a$(按数值最小)。如果不存在这样的 $a$,输出 $-1$。
例如 $\lvert7\rvert=1$、$\lvert105\rvert=3$,而 $\operatorname{sum}(105)=1+0+5=6$。
输入描述
每个测试文件均包含多组测试数据。第一行输入一个整数 $T$,满足 $1\le T\le5\times10^{4}$。
接下来 $T$ 行,每行输入一个整数 $x$,满足 $1\le x\le2500$。
输出描述
对于每组测试数据,输出一个整数,为满足条件的最小 $a$;若不存在,输出 $-1$。
样例 1
输入
4
9
20
23
18
输出
9
19
-1
18
样例解释:对 $x=9$,一位数 $9$ 满足 $1\times9=9$。对 $x=20$,一位数的数位和最多为 $9$,不行;两位数需要数位和为 $10$,最小的是 $19$。对 $x=23$,$23$ 是质数,只能拆成一位数且数位和为 $23$(不可能),或者 $23$ 位数且数位和为 $1$(超出 $10^{16}$),所以输出 $-1$。对 $x=18$,一位数不行;两位数需要数位和为 $9$,最小的是 $18$。
思路分析
第一步:换枚举对象。 直接枚举 $a$ 要扫到 $10^{16}$,不可行。突破口是位数 $L$ 只有 $17$ 种:只要位数定下来,数位和就被 $s=x/L$ 唯一确定,剩下的问题变成「用指定的数位和拼出最小的 $L$ 位数」。
第二步:定可行性条件。 位数更少的正整数一定更小,所以 $L$ 从 $1$ 往上试,第一个能构造出合法数的 $L$ 给出的就是答案。$L$ 可行需要同时满足
\[L\mid x,\qquad 1\le s=\frac{x}{L}\le 9L\]其中上界来自每一位最多为 $9$,下界来自 $a$ 是正整数、数位和至少为 $1$。
第三步:给定 $L$ 与 $s$ 时拼出最小的数。 数值先比高位,所以从高位往低位填,每一位尽量小:当前位不能小到让后面 $\text{rest}$ 位全填 $9$ 也凑不够剩余的数位和,于是当前位取
\[d=\max(\text{low},\; s-9\cdot\text{rest})\]其中 $\text{low}$ 在首位为 $1$、其余位为 $0$——首位不能为零,其它位可以。比 $d$ 更小的取值要么违反首位非零,要么让剩余位无法凑满,所以每一位都取到了可行范围内的最小值,拼出的数最小。
第四步:处理上界。 $10^{16}$ 是 $17$ 位数、数位和为 $1$,只对应 $x=17$;其余 $17$ 位数都超出区间。因此 $L$ 要试到 $17$,构造结果大于 $10^{16}$ 时跳过。$x=17$ 在 $L=1$ 时 $s=17>9$ 不可行,答案正是 $10^{16}$。大于 $17$ 的质数 $x$ 只有 $L=1$ 和 $L=x$ 两种拆法,前者数位和超过 $9$,后者位数超过 $17$,输出 $-1$。
第五步:预处理查表。 $T$ 最多 $5\times10^{4}$,而 $x$ 只有 $2500$ 种取值,先把 $1\sim2500$ 的答案全部算好,每组询问直接查表。
正确性说明
构造出的 $L$ 位数满足数位和为 $s$,于是 $\lvert a\rvert\cdot\operatorname{sum}(a)=L\cdot(x/L)=x$,可行性判定不放过任何解。数位贪心每一步都取「当前位最小且剩余位仍能凑满」的值,比它更小的值要么让首位为零,要么让剩余位无法凑满,因此对固定的 $L$ 与 $s$ 构造出的就是最小的 $L$ 位数。又因为任何 $L’<L$ 位数都小于任何 $L$ 位数,而所有更小的位数都已被证明不可行,所以第一个成功构造出的就是全区间内最小的 $a$。
题解代码
import sys
input = sys.stdin.readline
LIMIT = 10 ** 16 # 区间右端点,它本身是 17 位数
MAX_X = 2500
# 构造长度为 length、数位和为 s 的最小整数
def build_min(length, s):
num = 0
for i in range(length):
rest = length - i - 1 # 当前位之后还剩几位
d = 1 if i == 0 else 0 # 首位不能为 0,其余位最小可以放 0
# 后面每位最多放 9,放不下剩余数位和就只能把当前位抬高
while s - d > 9 * rest:
d += 1
num = num * 10 + d
s -= d
return num
# 求满足 数位长度 * 数位和 == x 的最小整数,不存在返回 -1
def min_number(x):
# 位数少的数一定更小,所以长度从小到大试,第一个可行的就是答案
for length in range(1, 18):
# 数位和必须是整数,长度不整除 x 的直接跳过
if x % length != 0:
continue
s = x // length
# 长度为 length 的数,数位和只能落在 [1, 9 * length]
if s > 9 * length:
continue
num = build_min(length, s)
# 17 位数里只有 10^16 本身不超界
if num <= LIMIT:
return num
return -1
def main():
t = int(input())
queries = [int(input()) for _ in range(t)]
# 预处理 1..2500 的全部答案,每组询问直接查表
answers = [0] * (MAX_X + 1)
for x in range(1, MAX_X + 1):
answers[x] = min_number(x)
out = [str(answers[x]) for x in queries]
sys.stdout.write("\n".join(out) + "\n")
main()
复杂度分析
时间复杂度:$O(V\cdot L^{2}+T)$,其中 $V=2500$ 是 $x$ 的取值个数、$L\le17$ 是最大位数。瓶颈是预处理:每个 $x$ 试至多 $17$ 种位数,每次构造逐位填、每位最多抬高 $9$ 次,总量约 $6.5\times10^{6}$ 次操作;查询每组为 $O(1)$。
空间复杂度:$O(V)$。存下 $1\sim2500$ 的答案表,与询问组数 $T$ 无关。
易错点
- $10^{16}$ 本身合法:它是 $17$ 位数、数位和为 $1$,对应 $x=17$,其余 $17$ 位数都要在构造后判超界跳过。
- 首位不能为 $0$,构造每一位时的下界与其他位不同,直接把所有位都按 $0$ 起步会得到前导零。
- 判定可行性时两个条件缺一不可:$L$ 要整除 $x$,商还要不超过 $9L$。
- 答案是 $10^{16}$ 量级,中间变量要用 64 位整数保存。
- 预处理表要覆盖 $1\sim2500$ 全部取值,不能只算询问里出现过的那些。
小结
- 可见选择题集中在大模型工程的落地细节:工具调用的前置校验、KV Cache 的显存治理、RAG 的排序截断,以及 SFT 数据的一致性;缺失的 15 题不做推测。
- 区间异或和题的关键是看出 $F(n)$ 按 $n\bmod 4$ 循环,把无穷枚举压成 6 个候选,并单独处理无解。
- 数位题的套路是「枚举位数 + 数位贪心」,真正要小心的是 $10^{16}$ 这个上界和首位非零。