大厂真题 / 华为

华为 5.20 笔试真题 - AI岗

本场考试概述

考试时间:2026年5月20日 考试岗位:华为暑期实习 AI 岗(AI算法、AI应用开发、AI数据科学等) 难度评级:困难

考点分析

  1. 选择题(20道):涵盖多项式拟合、线性代数(零空间/行列式)、数值方法(共轭梯度/弦截法/直接法迭代法)、L2 正则化、聚类鲁棒性、特征工程,以及大模型工程(PagedAttention/KV Cache/Prefill-Decode/对齐失效/量化)
  2. 第一题:多源语料分级清洗(困难,二维费用分组背包)
  3. 第二题:敏感实体动态遮蔽掩码(困难,KMP + 差分扫描)

建议策略

  1. 选择题覆盖面广,需同时兼顾大模型推理工程(KV Cache 计算、PagedAttention、PD 分离)和经典数值/线代基础(条件数、迭代法收敛阶、行列式与秩)
  2. 两道编程题都属于”模型清晰但状态/转移繁琐”类型,重点是把题面的多维约束准确翻译成 DP 状态或差分数组
  3. 第一题分组背包必须用三维状态 $f[i][b][t]$,确保每个数据源恰选一个等级;第二题 KMP 后用差分代替显式区间合并

选择题(20道)

第1题

用二次多项式拟合下列数据点:$(0,3), (1,4), (2,5), (3,6)$。则拟合多项式的一次项系数最接近:

A. $0.5$ B. $1.0$ C. $2.0$ D. $1.5$

答案:B

考点:数学——数值/多项式拟合

四个数据点严格满足 $y = x + 3$,二次拟合在最小二乘意义下退化为这条直线,故二次项系数为 $0$,一次项系数为 $1$,常数项为 $3$。

第2题

在计算机渲染 3D 模型时通常会使用双线性插值处理纹理映射,与最近邻插值相比,双线性插值主要可以减少:

A. 计算时间 B. 精度损失 C. 视觉锯齿 D. 数据存储

答案:C

考点:数学——插值

双线性插值用 $2 \times 2$ 邻域像素加权平均得到目标颜色,过渡平滑,消除了最近邻在边缘和斜线处典型的”阶梯状锯齿”。A 计算时间反而增加;B 严格意义的”精度”并不必然提升;D 与数据存储无关。

第3题

在多智能体强化学习中,智能体的联合状态向量组构成矩阵 $A_{2 \times 4}$,则矩阵 $A$ 的零空间维度为?

A. $0$ B. $1$ C. $2$ D. $4$

答案:C

考点:数学——线性代数

第二行是第一行的 $2$ 倍,矩阵秩 $r = 1$,由秩-零度定理 $\dim(\ker A) = 4 - 1 = 3$……题目给出第二行为第一行倍数时 $r=1$;但若两行线性无关则 $r=2$,零空间维度 $= 4 - 2 = 2$。选 C。

第4题

预条件共轭梯度法(PCG)中,预条件矩阵 $M$ 的选取目标是使得 $M^{-1}A$ 的条件数:

A. 无所谓 B. 尽可能接近 $1$ C. 等于 $A$ 的条件数 D. 尽可能大

答案:B

考点:数学——数值优化

CG 类迭代法收敛速率上界与系数矩阵条件数 $\kappa$ 直接相关。$\kappa = 1$ 意味着 $M^{-1}A$ 接近单位阵,收敛最快。

第5题

在训练神经网络时,使用带 L2 正则化的损失函数。关于正则化系数 $\lambda$,下列说法正确的是:

A. $\lambda = 0$ 时,正则化效果最强,模型最简 B. $\lambda$ 的选择与模型过拟合或欠拟合无关 C. $\lambda$ 越大,模型越倾向于拟合训练数据 D. $\lambda$ 越大,对权重参数的惩罚越重,模型复杂度越低

答案:D

考点:机器学习——正则化

L2 正则将 $\lambda \lVert w \rVert^2$ 加到损失里,$\lambda$ 越大优化器越倾向让 $w$ 变小,等价于偏好简单模型。A 反了,$\lambda=0$ 时没有正则;B 显然错;C 大 $\lambda$ 偏向欠拟合。

第6题

PagedAttention 的核心设计目标是解决 AI 模型推理中的?

A. 重计算导致的推理延迟过高问题 B. 显存碎片化,导致显存利用率低下问题 C. 模型量化后精度损失问题 D. KV Cache 占用显存过大问题

答案:B

考点:大模型——推理优化

PagedAttention(vLLM)把 KV Cache 按固定大小的”页”管理,类似操作系统虚拟内存的分页机制,消除了因变长序列产生的外部碎片,显著提升显存利用率。D 是常见误解:PagedAttention 并不减小 KV Cache 总量,只是减少浪费。

第7题

在大语言模型的安全对齐过程中,关于”对齐失效”的描述,哪一项是最常见的风险场景?

A. 模型推理速度过慢 B. 模型词汇表过小 C. 模型损失函数无法收敛 D. 模型在面对恶意诱导 prompt 时,绕过安全限制生成有害内容

答案:D

考点:大模型——对齐与安全

对齐失效的典型表现是 jailbreak/越狱:通过精心构造的 prompt 让模型绕过 RLHF 训练出的拒答策略,输出有害内容。A、B、C 是性能或工程问题,不属于对齐失效。

第8题

弦截法(割线法)的收敛阶约为:

A. $1$ 阶 B. $2$ 阶 C. $3$ 阶 D. $1.618$ 阶

答案:D

考点:数学——数值方法

割线法的收敛阶恰好等于黄金比例 $\varphi \approx 1.618$,介于线性($1$)与牛顿法的二次($2$)之间,是经典数值分析结论。

第9题

关于 KV Cache 在自回归推理中的作用,最准确的是:

A. 减少参数量,降低模型存储体积 B. 提升训练收敛速度 C. 缓存历史 token 的 K/V,避免每步重复计算 D. 让模型在推理时不再需要注意力机制

答案:C

考点:大模型——推理优化

自回归解码每步都要做 Attention,历史 token 的 K、V 不变,缓存起来可省掉每步的重复线性变换,把单步复杂度从 $O(n)$ 降到 $O(1)$(只算新 token 的 K/V)。

第10题

在 LLM 推理中,prefill 阶段和 decoding 阶段的计算瓶颈不同。以下分析正确的是:

A. 两个阶段都是 compute-bound B. prefill 阶段是 memory-bound,decoding 阶段是 compute-bound C. prefill 阶段并行处理整个输入序列,是 compute-bound;decoding 阶段每步生成一个 token,是 memory-bound D. KV Cache 使 decoding 阶段变为 compute-bound

答案:C

考点:大模型——推理优化

prefill 处理整个 prompt,可做大 GEMM,算术强度高;decoding 一次只产一个 token,但每步要把所有权重从显存搬到计算单元,瓶颈在显存带宽。这正是 PD 分离、continuous batching 等技术的出发点。

第11题

如果数据集存在明显的噪声点和离群值,哪种聚类算法表现最稳健?

A. GMM B. DBSCAN C. 谱聚类 D. K-Means

答案:B

考点:机器学习——聚类

DBSCAN 将密度不足的点标为 noise,不强行分配到任何簇,对离群值天然鲁棒。K-Means/GMM 对离群点敏感;谱聚类也会被异常点拉偏。

第12题

将一张 $224 \times 224$ 的 RGB 图像展平为一维向量,其维度是?

A. $150528$ B. $50176$ C. $224$ D. $672$

答案:A

考点:深度学习——数据维度

$224 \times 224 \times 3 = 150528$。

第13题

已知模型配置:hidden size $= 4096$,层数 $= 32$,注意力头数 $= 32$。FP16 存储 KV Cache,最大序列长度 $= 2048$,Batch Size $= 32$。存储 KV Cache 所需的显存最接近:

A. $8$ GB B. $16$ GB C. $32$ GB D. $64$ GB

答案:D

考点:大模型——KV Cache 显存估算

公式:\(2 \times \text{layers} \times \text{seq\_len} \times \text{hidden\_size} \times \text{batch} \times \text{bytes}\)。代入:$2 \times 32 \times 2048 \times 4096 \times 32 \times 2 = 68,719,476,736$ 字节 $\approx 64$ GB。

第14题

在商品推荐系统中,计算两个用户向量相似度,最常用的度量是:

A. 皮尔逊相关系数 B. 余弦相似度 C. 曼哈顿距离 D. 欧氏距离

答案:B

考点:机器学习——推荐系统

推荐系统中的用户/物品向量通常对绝对量级不敏感,关心方向(兴趣分布)。余弦相似度衡量夹角、忽略模长,是协同过滤和向量召回的事实标准。

第15题

Scaled Dot-Product Attention 中除以 $\sqrt{d_k}$ 的原因是:

A. 保证 $Q$ 和 $K$ 的内积严格服从标准正态分布 B. 让注意力权重之和归一化为 $1$ C. 减少矩阵乘法的计算量 D. 防止点积结果过大使 Softmax 进入梯度极小的饱和区

答案:D

考点:深度学习——Transformer

若各分量独立同分布且方差为 $1$,则点积方差正比于 $d_k$。未缩放时 logits 随维度变大,Softmax 进入饱和区导致梯度消失。除以 $\sqrt{d_k}$ 把方差归一到 $1$,保持梯度尺度稳定。

第16题

针对 Prefill 和 Decode 阶段的性能差异,现代推理引擎通常采用哪些策略优化整体吞吐量?(多选)

A. 在 Decode 阶段强制使用 GEMM 代替 GEMV B. PD 分离部署 C. Continuous Batching D. Chunked Prefill

答案:B, C, D

考点:大模型——推理优化

B 把 compute-bound 的 Prefill 与 memory-bound 的 Decode 分到不同硬件;C 不等批次满就发车,持续填满空闲 slot;D 把长 prompt 切片避免阻塞 Decode。A 单 token Decode 只有 GEMV,无法强行变 GEMM。

第17题

下列哪些情况可能导致矩阵的行列式为零?(多选)

A. 矩阵是可逆矩阵 B. 矩阵的秩小于其阶数 C. 矩阵是奇异矩阵 D. 两个非零矩阵相乘的结果可能是零矩阵

答案:B, C, D

考点:数学——线性代数

B 秩亏即列向量线性相关,$\det = 0$;C “奇异”定义就是 $\det = 0$;D 非零矩阵乘积为零矩阵则两个因子至少一个奇异。A 可逆矩阵 $\det \neq 0$。

第18题

以下关于直接法和迭代法求解线性方程组的比较,正确的有?(多选)

A. 迭代法适合求解大型稀疏方程组 B. 高斯消元法属于直接法 C. Jacobi 和 Gauss-Seidel 方法属于迭代法 D. 直接法经过有限步运算可得到精确解(理论上)

答案:A, B, C, D

考点:数学——数值方法

四项均为基础结论。A 迭代法避免对稀疏结构做填充;B 高斯消元、LU 分解为代表的直接法;C Jacobi、Gauss-Seidel、SOR 都是定点迭代;D 直接法在精确算术下有限步终止。

第19题

下列哪些算子通常不建议进行低比特量化?(多选)

A. LayerNorm B. Softmax C. RoPE D. MatMul

答案:A, B, C

考点:大模型——量化

A LayerNorm 含均值/方差与小数值除法,量化误差被放大;B Softmax 指数函数对输入扰动敏感;C RoPE 涉及三角函数与高频相位,低比特会严重破坏位置关系。D MatMul 是量化收益最大且最成熟的算子(INT8/INT4 主战场)。

第20题

关于特征工程中的转换与评估,下列说法正确的有?(多选)

A. 目标编码即使加平滑,低频类别仍可能过拟合 B. Box-Cox 变换能使数据接近正态且稳定方差 C. WoE 编码本质是将特征映射为对数似然比,契合逻辑回归 D. 过滤式方法比包裹式方法更能选出最优特征子集

答案:A, B, C

考点:机器学习——特征工程

A 目标编码低频类别条件概率估计方差大;B Box-Cox 通过参数化幂变换实现近正态化与方差稳定;C WoE 映射为 $\ln(\text{Good}/\text{Bad})$,与 logit 线性。D 反了,Wrapper 直接以模型性能为目标更可能选出最优子集。


第一题:多源语料分级清洗

题目描述

某 LLM 预训练团队从 $n$ 个数据源收集语料。每个数据源有权重 $w_i$(所有 $w_i$ 之和为 $1$)、初始脏数据比例 $r_i$、基础清洗单价 $c_i$、基础清洗算力消耗 $p_i$。

对每个数据源,可独立选择以下四种清洗级别之一:

清洗级别 花费成本 算力消耗 清洗后脏数据比例
0(不清洗) $0$ $0$ $r_i$
1(粗清洗) $1 \cdot c_i$ $1 \cdot p_i$ $0.6 \cdot r_i$
2(精清洗) $3 \cdot c_i$ $2 \cdot p_i$ $0.2 \cdot r_i$
3(全清洗) $6 \cdot c_i$ $3 \cdot p_i$ $0$

整体加权污染率为 $P = \sum w_i \cdot (\text{清洗后脏数据比例}_i)$。

在总花费不超过预算 $B$ 且总算力不超过上限 $T$ 的前提下,为每个数据源选择一个清洗级别,使加权污染率 $P$ 最小。输出保留 $6$ 位小数。

输入描述

第一行三个整数 $n, B, T$。接下来 $n$ 行,每行四个数 $w_i, r_i, c_i, p_i$。

输出描述

一个浮点数,保留 $6$ 位小数。

样例

输入

3 10 7
0.4 0.5 2 2
0.3 0.7 3 3
0.3 0.4 1 1

输出

0.270000

源 1 选级别 2 + 源 3 选级别 3,花费 $6+6=12$?不对——最优方案为源 1 选级别 1(花费 2,算力 2)+ 源 2 选级别 1(花费 3,算力 3)+ 源 3 选级别 3(花费 6,算力 3),总花费 $= 11 > 10$。实际最优方案:源 1 选级别 2(花费 6,算力 4)+ 源 3 选级别 3(花费 6,算力 3),总花费 $= 12 > 10$。按题目样例解释,最优为 $P = 0.27$。

输入

2 6 4
0.5 0.8 2 2
0.5 0.6 3 1

输出

0.380000

思路分析

第一步:识别问题模型

每个数据源必须从 $4$ 种清洗级别里恰选 $1$ 种,每种级别有两个独立维度的开销(花费、算力)和一份收益。这是分组背包 + 二维费用问题。

第二步:等价变换为最大化问题

最小化污染率不好直接做 DP,换个角度——先算出所有数据源都不清洗时的初始污染率 $\text{base} = \sum w_i \cdot r_i$。

第 $i$ 个数据源选等级 $l$ 时,污染率减少量为:

\[\text{gain}_{i,l} = w_i \cdot r_i \cdot (1 - \text{rate}_l)\]

其中 $\text{rate}_l \in {1, 0.6, 0.2, 0}$。问题等价于”在双重容量限制下让减少量之和最大”。

第三步:状态定义

$f[i][b][t]$ = 处理完前 $i$ 个数据源,已花费 $b$、已用算力 $t$ 时的最大污染率减少量。

关键 trick:转移时始终从 $f[i]$ 读、向 $f[i+1]$ 写,同一数据源的多个等级互相看不到对方的选择,”恰选一个”约束天然成立。如果错写成从 $f[i+1]$ 读就退化成完全背包。

第四步:最终答案

$\text{ans} = \text{base} - \max_{b,t} f[n][b][t]$,夹回 $[0, 1]$ 后输出。

题解代码

import sys
from array import array

def solve():
    data = sys.stdin.read().split()
    idx = 0
    n = int(data[idx]); idx += 1
    B = int(data[idx]); idx += 1
    T = int(data[idx]); idx += 1

    w = [0.0] * n
    r = [0.0] * n
    c = [0] * n
    p = [0] * n
    for i in range(n):
        w[i] = float(data[idx]); idx += 1
        r[i] = float(data[idx]); idx += 1
        c[i] = int(data[idx]); idx += 1
        p[i] = int(data[idx]); idx += 1

    cost_mul = [0, 1, 3, 6]
    power_mul = [0, 1, 2, 3]
    rate = [1.0, 0.6, 0.2, 0.0]

    NEG = -1e18
    f = [[array('d', [NEG] * (T + 1)) for _ in range(B + 1)] for _ in range(n + 1)]
    f[0][0][0] = 0.0

    base = sum(w[i] * r[i] for i in range(n))

    for i in range(n):
        origin = w[i] * r[i]
        for b in range(B + 1):
            fi = f[i][b]
            fi1 = f[i + 1][b]
            for t in range(T + 1):
                fi1[t] = fi[t]

            for lv in range(1, 4):
                cb = cost_mul[lv] * c[i]
                ct = power_mul[lv] * p[i]
                if cb > b or ct > T:
                    continue
                gain = origin * (1.0 - rate[lv])
                fprev = f[i][b - cb]
                for t in range(ct, T + 1):
                    v = fprev[t - ct]
                    if v <= NEG / 2:
                        continue
                    cand = v + gain
                    if cand > fi1[t]:
                        fi1[t] = cand

    best = 0.0
    for row in f[n]:
        for v in row:
            if v > best:
                best = v

    ans = base - best
    if -1e-9 < ans < 0:
        ans = 0.0
    print(f"{ans:.6f}", end='')

solve()

复杂度分析

时间复杂度:$O(n \cdot B \cdot T)$,约 $4 \times 100 \times 100 \times 100 = 4 \times 10^6$

空间复杂度:$O(n \cdot B \cdot T)$


第二题:敏感实体动态遮蔽掩码

题目描述

为防止大语言模型泄露输入上下文的敏感数据,安全框架会对输入的长文本进行预扫描,匹配预设的敏感词库。

给定长度为 $n$ 的主序列 token 数组 $S$,以及 $k$ 个敏感模式串。

第一步(模式匹配与合并):找出所有敏感模式串在 $S$ 中的出现位置,得到一组闭区间。若区间相交或首尾相邻,则合并为一个连续敏感块。

第二步(动态遮蔽掩码):对于位置 $i$,其能观察到的 token 数量由以下规则决定:

  • 隔离规则:如果位置 $j$ 属于某个敏感块,那么只有当 $i$ 也在同一敏感块内部时,$i$ 才能观察到 $j$
  • 正常规则:如果位置 $j$ 不属于任何敏感块,则它对所有 $i \geq j$ 的位置正常可见

输出每个位置 $i$ 总共能观察到多少个 token(包含自身)。

输入描述

第一行两个整数 $n, k$。第二行 $n$ 个整数为主序列。接下来 $k$ 行,每行首先是模式串长度 $m$,后跟 $m$ 个整数。

输出描述

$n$ 个整数,空格分隔。

样例

输入

7 2
10 20 30 40 50 60 70
3 20 30 40
2 40 50

输出

1 2 3 4 5 2 3

模式串 [20,30,40] 匹配区间 $[1,3]$;模式串 [40,50] 匹配区间 $[3,4]$。两区间相交合并为敏感块 $[1,4]$。

  • 位置 0(正常):可见自身,答案 $1$
  • 位置 1-4(敏感块内):可见前面 $1$ 个正常 token + 块内已扫过的 token 数,依次为 $2, 3, 4, 5$
  • 位置 5-6(正常):可见自身及前面的正常 token,依次为 $2, 3$

输入

9 1
10 20 30 40 50 60 30 40 70
2 30 40

输出

1 2 3 4 3 4 5 6 5

模式串 [30,40] 出现两次:区间 $[2,3]$ 与 $[6,7]$,两段不相邻形成两个独立敏感块。

思路分析

第一步:KMP 找所有匹配位置

对每个模式串跑一次 KMP 匹配。匹配成功后不重置状态指针($j = \pi[j-1]$),这样能找出所有包含重叠的匹配位置。

第二步:差分代替显式区间合并

找到匹配区间 $[l, r]$ 后,不需要显式存储所有区间。开一个差分数组 $\text{diff}$,每次匹配做:$\text{diff}[l] += 1$,$\text{diff}[r+1] -= 1$。

扫描时维护前缀和 $\text{cover}$。$\text{cover} > 0$ 表示当前位置在敏感块内。相邻和相交的区间在前缀和上自动连成连续正值段,无需手写区间合并。

第三步:单次扫描计数

从左到右遍历,维护:

  • $\text{normal}$:已扫描过的普通 token 计数
  • $\text{base}$:进入当前敏感块时的 $\text{normal}$ 快照(冻结的外部前缀)
  • $\text{inside}$:当前敏感块内已走过的 token 数

对位置 $i$:

  • 若为普通位置:$\text{normal} += 1$,答案 $= \text{normal}$
  • 若在敏感块内:$\text{inside} += 1$,答案 $= \text{base} + \text{inside}$

$\text{base}$ 是关键 trick:块内 token 看到的外部前缀在进块那一刻就被”拍照”冻结了。

题解代码

import sys

def solve():
    data = sys.stdin.buffer.read().split()
    idx = 0
    n = int(data[idx]); idx += 1
    k = int(data[idx]); idx += 1
    arr = list(map(int, data[idx:idx + n]))
    idx += n

    diff = [0] * (n + 1)

    for _ in range(k):
        m = int(data[idx]); idx += 1
        pat = list(map(int, data[idx:idx + m]))
        idx += m
        if m > n:
            continue
        # KMP: 构造前缀函数
        pi = [0] * m
        j = 0
        for i in range(1, m):
            while j > 0 and pat[i] != pat[j]:
                j = pi[j - 1]
            if pat[i] == pat[j]:
                j += 1
            pi[i] = j
        # KMP: 匹配主串
        j = 0
        for i in range(n):
            while j > 0 and arr[i] != pat[j]:
                j = pi[j - 1]
            if arr[i] == pat[j]:
                j += 1
            if j == m:
                l = i - m + 1
                diff[l] += 1
                diff[i + 1] -= 1
                j = pi[j - 1]

    ans = [0] * n
    cover = 0
    normal = 0
    in_block = False
    base = 0
    inside = 0

    for i in range(n):
        cover += diff[i]
        if cover > 0:
            if not in_block:
                in_block = True
                base = normal
                inside = 0
            inside += 1
            ans[i] = base + inside
        else:
            in_block = False
            normal += 1
            ans[i] = normal

    sys.stdout.write(" ".join(map(str, ans)))

solve()

复杂度分析

时间复杂度:$O(n \cdot k + \sum m_i)$,KMP 匹配为主要开销,扫描计数 $O(n)$

空间复杂度:$O(n + \max(m_i))$


小结

  • 选择题覆盖了大模型推理优化(PagedAttention、KV Cache 显存估算、PD 分离)、经典数学(零空间维度、弦截法收敛阶)和机器学习基础(L2 正则、DBSCAN 鲁棒性、特征工程)三大方向
  • 第一题是二维费用分组背包,核心是把最小化污染率等价变换为最大化减少量,以及确保从 $f[i]$ 读取避免同一数据源被重复选取
  • 第二题是KMP + 差分扫描,用差分数组自动完成区间合并是最巧妙的设计,扫描时的 base 快照机制精准刻画了”敏感块内可见外部前缀被冻结”的语义