大厂真题 / 华为

华为 4.29 笔试真题 - AI岗

本场考试概述

考试时间:2026年4月29日 考试岗位:AI岗(国内) 难度评级:中等偏难

考点分析

  1. 选择题(20道):机器学习基础(NMF/LDA/正则化/混淆矩阵)、深度学习(MobileNet/FP16/AdamW/Dead ReLU/多任务学习)、大模型(指令遵循评测/张量并行/RLHF/PagedAttention)、数学(线性代数/概率论/数值计算)、GPU架构
  2. 第一题:LSTM 前向传播(难度困难)
  3. 第二题:大模型语料清洗 · 字符串模拟(难度中等)

建议策略

  1. 选择题重点掌握 ML/DL 基础概念,大模型相关题目(RLHF、张量并行、PagedAttention)属于高难度,先保住入门和简单题
  2. 第一题 LSTM 需要熟悉矩阵运算和四个门的计算顺序,理解输入格式是关键
  3. 第二题字符串模拟规则清晰,按顺序实现五条清洗规则即可

选择题(20道)

第1题

非负矩阵分解(NMF)的适用场景是?

A. 数据含负值的场景 B. 矩阵可逆的场景 C. 数据非负且需解释性的场景(如文本聚类) D. 高维数据降维场景

答案:C

考点:机器学习——降维与矩阵分解

NMF 要求输入矩阵元素非负,分解后的因子矩阵也非负,因此具有天然的可解释性(每个分量可理解为”部分的叠加”),常用于文本聚类、图像特征提取等场景。A 违反非负约束,B/D 不是 NMF 的核心优势。

第2题

矩阵的条件数 $\kappa(A)$ 的定义为?

A. $\lVert A \rVert + \lVert A^{-1} \rVert$ B. $\lVert A \rVert - \lVert A^{-1} \rVert$ C. $\lVert A \rVert / \lVert A^{-1} \rVert$ D. $\lVert A \rVert \cdot \lVert A^{-1} \rVert$

答案:D

考点:数学——线性代数

矩阵条件数定义为 $\kappa(A) = \lVert A \rVert \cdot \lVert A^{-1} \rVert$,衡量矩阵求逆或线性方程组求解时对输入扰动的敏感程度。条件数越大,矩阵越”病态”,数值求解越不稳定。

第3题

在 CNN 架构演进中,MobileNet 核心创新点在于将标准卷积分解为?

A. 空间卷积和时间卷积 B. 深度卷积(Depthwise)和逐点卷积(Pointwise) C. 1×1 卷积和 3×3 卷积的并行计算 D. 全连接层和池化层的组合

答案:B

考点:深度学习——CNN

MobileNet 将标准卷积分解为 Depthwise Convolution(每个通道独立做空间卷积)和 Pointwise Convolution(1×1 卷积做通道融合),大幅减少参数量和计算量,适合移动端部署。

第4题

关于线性判别分析(LDA),下列说法正确的是?

A. LDA 是无监督降维方法 B. LDA 的目标是最大化类间散度与类内散度的比值 C. LDA 降维后的维度可以任意指定,最多等于特征数 D. LDA 适用于任何类型的数据分布

答案:B

考点:机器学习——降维与矩阵分解

LDA 是有监督降维方法(A 错),目标是最大化 $\frac{S_B}{S_W}$(类间散度/类内散度),使投影后类间距离大、类内距离小。降维后维度最多为 $C-1$($C$ 为类别数),不是特征数(C 错)。LDA 假设各类服从高斯分布且协方差相同(D 错)。

第5题

在对大模型进行指令遵循能力评测时,下列说法正确的是?

A. 在使用 LLM-as-a-judge 时,评测模型存在”长度偏见(Length Bias)” B. 应完全依赖 ROUGE-L 指标来评估指令遵循能力 C. MMLU 基准测试主要采用多轮对话形式,是衡量对齐水平最直接的指标 D. Pass@1 表现优异可直接断定模型在复杂逻辑推理任务中具有极高鲁棒性

答案:A

考点:大模型——评测与对齐

A 正确指出了 LLM-as-a-judge 的已知缺陷——评测模型倾向于给更长、信息更密集的输出打高分。B 错在”完全依赖”单一指标不可靠;C 错在 MMLU 是多项选择题形式,衡量知识能力而非对齐水平;D 错在 Pass@1 只衡量单次生成正确率,无法推断鲁棒性。

第6题

在深度学习中使用半精度(FP16)训练的主要动机是?

A. 降低内存占用与加速计算 B. 增加模型的泛化能力 C. 提高数值稳定性 D. 减少舍入误差

答案:A

考点:深度学习——训练优化

FP16 占用 2 字节(FP32 为 4 字节),显存减半且可利用 GPU Tensor Core 加速矩阵运算。FP16 实际上会降低数值精度(C/D 错),需要配合混合精度训练(loss scaling)来保证稳定性。与泛化能力无直接关系(B 错)。

第7题

在多任务学习中,共享主干模型的主要优势体现在哪个方面?

A. 提升任务之间的隔离性,防止相互干扰 B. 确保所有任务的训练速度一致 C. 减少模型的部署成本,不考虑训练效率 D. 通过共享主干实现参数、计算和表征的复用

答案:D

考点:深度学习——多任务学习

共享主干(shared backbone)的核心优势是参数复用、计算复用和跨任务的表征迁移。A 恰好相反,共享会引入任务间耦合;B 无法保证速度一致;C 表述片面。

第8题

在 GPU 的存储层次中,哪一种存储器具有最低的访问延迟和最高的聚合带宽?

A. 系统内存 B. HBM(高带宽内存) C. SRAM(共享内存 / 寄存器) D. L2 缓存

答案:C

考点:深度学习——GPU架构

GPU 存储层次从快到慢:寄存器/共享内存(SRAM,片上)→ L2 缓存 → HBM(片外高带宽显存)→ 系统内存(通过 PCIe)。SRAM 位于 SM 内部,访问延迟约 1-2 个时钟周期,聚合带宽可达数十 TB/s,远超 HBM 的约 3 TB/s。

第9题

在逻辑回归中加入 L2 正则化的主要目的是?

A. 防止过拟合,提高泛化能力 B. 加速梯度下降收敛 C. 自动进行特征选择 D. 处理类别不平衡问题

答案:A

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

L2 正则化通过在损失函数中添加 $\lambda \lVert w \rVert^2$ 惩罚项,约束权重不要过大,从而降低模型复杂度、防止过拟合。C 描述的是 L1 正则化(产生稀疏解)的特性;B/D 不是 L2 正则化的主要目的。

第10题

在 Megatron-LM 的张量并行架构中,对 MLP 模块两层全连接层的切分策略是?

A. 第一个线性层按列切分(Column-parallel),第二个按行切分(Row-parallel) B. 两个线性层都按行切分 C. 第一个线性层按行切分,第二个按列切分 D. 两个线性层都按列切分

答案:A

考点:大模型——分布式训练

Megatron-LM 对 MLP 采用”列切分→行切分”策略:第一层按列切分,每个 GPU 独立计算部分输出(无需通信);第二层按行切分,每个 GPU 的局部结果通过 All-Reduce 汇总。这种组合只需要一次 All-Reduce 通信,最小化了跨 GPU 开销。

第11题

关于 SFT 与基于偏好或奖励的强化学习阶段,下列哪项表述更准确?

A. 强化学习阶段不需要任何反馈信号 B. 两个阶段目标完全相同且可互相替代 C. SFT 主要模仿高质量示例,强化学习阶段进一步按奖励或偏好优化行为 D. SFT 只用于图像模型

答案:C

考点:大模型——RLHF

SFT 阶段通过监督学习让模型模仿高质量的指令-回答对;RLHF/DPO 等强化学习阶段则基于人类偏好反馈或奖励模型进一步优化模型行为,使其更符合人类期望。A 错(RL 依赖奖励信号),B 错(目标不同),D 错(SFT 广泛用于语言模型)。

第12题

在 AdamW 中,”W”代表什么改进?

A. Windowing(窗口优化) B. Warming(预热改进) C. Weight Initialization(权重初始化改进) D. Weight Decay decoupling(解耦权重衰减)

答案:D

考点:深度学习——优化器

AdamW 由 Loshchilov & Hutter 提出,将权重衰减从梯度更新中解耦出来。原始 Adam 中 L2 正则化与自适应学习率交互导致正则化效果受损,AdamW 直接在参数更新后施加权重衰减 $w \leftarrow (1-\lambda)w$,正则化效果更稳定。

第13题

一个硬币掷出正面的概率是 0.6,抛掷 5 次,恰好出现 3 次正面的概率是?

A. $0.6^3 \times 0.4^2$ B. $\binom{5}{3} \times 0.6^2 \times 0.4^3$ C. $\binom{5}{3} \times 0.6^5$ D. $\binom{5}{3} \times 0.6^3 \times 0.4^2$

答案:D

考点:数学——概率

二项分布公式 $P(X=k) = \binom{n}{k} p^k (1-p)^{n-k}$,代入 $n=5, k=3, p=0.6$ 得 $\binom{5}{3} \times 0.6^3 \times 0.4^2$。A 漏掉了组合数 $\binom{5}{3}$,B/C 的指数分配错误。

第14题

前向差分、中心差分和 Richardson 外推法的误差阶数分别是?

A. 前向差分:$O(h)$,中心差分:$O(h^2)$,Richardson 外推:$O(h^4)$ B. 前向差分:$O(h^2)$,中心差分:$O(h^4)$,Richardson 外推:$O(h^6)$ C. 三种方法的误差阶数相同 D. 步长越小,数值微分结果越精确

答案:A

考点:数学——数值计算

前向差分 $\frac{f(x+h)-f(x)}{h}$ 截断误差为 $O(h)$;中心差分 $\frac{f(x+h)-f(x-h)}{2h}$ 对称消去了一阶误差项,精度为 $O(h^2)$;Richardson 外推通过组合不同步长的中心差分进一步消除高阶误差,达到 $O(h^4)$。D 忽略了舍入误差——步长过小时浮点误差反而增大。

第15题

关于 PagedAttention 与传统 Attention 的显存管理区别,下列说法错误的是?

A. 传统 Attention 需为每个序列分配连续显存存储 KV Cache,易产生碎片化 B. PagedAttention 将 KV Cache 分页存储,可利用离散显存碎片,提升利用率 C. PagedAttention 通过页表管理 KV Cache 的分页,实现分配与回收 D. 传统 Attention 的 KV Cache 显存占用与序列长度正相关,PagedAttention 可突破该关联

答案:D

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

PagedAttention 改变的是显存的管理方式(从连续分配变为分页管理),但 KV Cache 的总显存占用仍然与序列长度成正比——每个 token 仍需存储 K/V 向量。PagedAttention 的优势是减少碎片化和浪费(A/B/C 均正确),而非突破 KV Cache 与序列长度的正相关关系。

第16题

关于二分类混淆矩阵,下列说法正确的有?

A. 召回率(Recall) = TP / (TP + FN) B. 真正例率 TPR = TN / (TN + FP) C. 准确率(Accuracy) = (TP + TN) / (TP + TN + FP + FN) D. 精确率(Precision) = TP / (TP + FP)

答案:A, C, D

考点:机器学习——评价指标

A 正确,召回率 = TP/(TP+FN),衡量实际正例中被正确预测的比例。B 错误,TPR = TP/(TP+FN),与召回率相同;TN/(TN+FP) 是特异度(Specificity)。C 正确,准确率 = 正确预测总数/样本总数。D 正确,精确率 = 预测为正例中实际为正例的比例。

第17题

对两个非零向量施加正交变换矩阵 $Q$(满足 $Q^TQ = I$),下列哪些度量值保持不变?

A. 向量之间的内积 B. 向量之间的欧几里得距离 C. 向量之间的曼哈顿距离 D. 向量之间的余弦相似度

答案:A, B, D

考点:数学——线性代数

正交变换保持内积不变:$(Qu)^T(Qv) = u^T Q^T Q v = u^T v$(A 正确)。由内积不变可推出 L2 范数不变,进而欧几里得距离不变(B 正确)。余弦相似度由内积和 L2 范数计算,均不变故余弦相似度也不变(D 正确)。但曼哈顿距离(L1 范数)依赖各坐标分量的绝对值之和,正交变换会改变分量分布,L1 距离一般不保持(C 错误)。

第18题

关于事件 A, B, C,下面哪些说法正确?

A. 若 $P(AB) = P(A)P(B)$ 且 $P(A) > 0$,则 $A$ 和 $B$ 独立 B. $P(AB) = P(A)P(B \mid A)$ 恒成立 C. 若 $A$ 与 $B$ 独立,则 $P(A \mid B) = P(A)$ D. 若 $A$ 和 $B$ 独立且 $A$ 和 $C$ 独立,则 $A$ 与 $BC$ 独立

答案:A, C

考点:数学——概率

A 正确,$P(AB) = P(A)P(B)$ 等价于独立性定义。B 看起来像乘法公式,但当 $P(A)=0$ 时条件概率 $P(B \mid A)$ 无定义,故不恒成立。C 正确,这是独立性的直接推论。D 错误,两两独立不能推出 $A$ 与 $BC$ 独立,需要相互独立的更强条件。

第19题

关于大规模深度学习模型训练中统计分布的应用,下列说法正确的有?

A. 当 batch size 足够大时,模型梯度的分布通常趋向于高斯分布 B. 若神经元权重之间相互独立且联合分布服从多元正态分布,则协方差矩阵必然是对角矩阵 C. 若激活值分布为 Laplace 分布,线性对称量化效果通常优于非线性量化 D. 为了最小化 MSE,最优量化截断阈值通常小于观测最大值

答案:A, B, D

考点:深度学习——训练优化

A 正确,由中心极限定理,batch 梯度是多个样本梯度的均值,batch size 越大越趋近高斯分布。B 正确,多元正态分布中独立等价于不相关,协方差矩阵的非对角元素为 0。C 错误,Laplace 分布尖峰厚尾,线性对称量化在尾部浪费精度,非线性量化能更好适配。D 正确,牺牲极端值精度以换取主体分布区间更高的量化分辨率,整体 MSE 更小。

第20题

关于 Dead ReLU 问题,以下描述正确的有?

A. 如果学习率过大,可能导致权重更新幅度过大,使得神经元永远落在 ReLU 的负半轴区域 B. Leaky ReLU 可以有效缓解 Dead ReLU 问题 C. 当输入小于零时,ReLU 的梯度恒为 0,导致权重无法更新 D. 一旦神经元”死亡”,它在后续的训练中永远不会被激活

答案:A, B, C

考点:深度学习——激活函数

A 正确,过大的学习率导致权重剧烈更新,神经元的加权输入可能对所有样本都变为负值。B 正确,Leaky ReLU 在负区域保留小梯度(如 $0.01x$),使权重仍可更新。C 正确,$\text{ReLU}(x) = 0\ (x < 0)$,梯度为零导致权重无法通过反向传播更新。D 不完全正确——虽然死亡神经元自身权重不再更新,但上游层权重仍在训练,输入分布的变化有可能使该神经元”复活”。


第一题:基于LSTM进行室内温度预测

题目描述

在智能家居系统中,通过传感器采集过去一段时间内的环境数据,使用 LSTM 模型预测室内温度。系统每 5 分钟采集一次数据,包括 5 个特征:室内温度、室外温度、空调功率、门窗开合状态、室内人员数量。

给定过去 $T$ 个时间步的数据($B$ 个房间、每房间 $D=5$ 个特征、隐藏层维度 $H$),使用 LSTM 的四个门执行前向传播,输出每个时间步的隐藏状态和最终细胞状态。

LSTM 核心公式($\sigma$ 为 sigmoid 激活函数):

\[f_t = \sigma(x_t W_{xf} + h_{t-1} W_{hf} + b_f)\] \[i_t = \sigma(x_t W_{xi} + h_{t-1} W_{hi} + b_i)\] \[\tilde{c}_t = \tanh(x_t W_{xc} + h_{t-1} W_{hc} + b_c)\] \[c_t = f_t \odot c_{t-1} + i_t \odot \tilde{c}_t\] \[o_t = \sigma(x_t W_{xo} + h_{t-1} W_{ho} + b_o)\] \[h_t = o_t \odot \tanh(c_t)\]

初始状态 $h_0 = 0$,$c_0 = 0$。

输入描述

第一行 $T, B, D, H$ 四个正整数。接下来 $T \times B$ 行,每行 $D$ 个浮点数,表示输入序列(按时间步顺序,每个时间步按批次顺序排列)。最后四组参数分别对应输入门、遗忘门、输出门和候选细胞状态,每组包含输入权重($D \times H$ 个值)、隐藏权重($H \times H$ 个值)、偏置($H$ 个值),所有参数按行优先展平。

输出描述

第一行输出所有时间步隐藏状态($T \times B \times H$ 个值),第二行输出最终细胞状态($B \times H$ 个值),保留 4 位小数。

样例

输入

1 1 5 2
2.5 5.0 3.2 5.0 1
0.1 0.1 0.3 3.4 0.5 0.4 0.7 0.3 0.2 1.0 0.7 0.5
0.8 1.0 1.1 1.4
0.1 0.7 0.1 1.4 0.5 0.6 0.3 0.2 0.3 1.0 0.8 0.7
0.7 1.1 1.2 1.2
0.1 0.8 3.3 0.4 0.1 0.5 0.4 0.8 0.9 1.0 0.6 0.9
0.5 1.2 1.1 1.5
0.1 0.1 0.3 0.4 0.5 0.6 0.6 0.8 0.2 1.0 0.7 0.1
0.9 1.3 1.6 1.2

输出

0.7615 0.7616
0.9997 1.0000

思路分析

第一步:理解 LSTM 的四个门

LSTM 的核心是四个门,它们结构相同——都是”线性变换 + 激活函数”,区别仅在于激活函数(sigmoid 或 tanh)和参数:

  • 遗忘门 $f_t$(sigmoid):决定保留多少旧的细胞状态
  • 输入门 $i_t$(sigmoid):决定写入多少新信息
  • 候选细胞 $\tilde{c}_t$(tanh):待写入的新内容
  • 输出门 $o_t$(sigmoid):筛选细胞状态的暴露部分

每个门的计算都是:$x_t W_x + h_{t-1} W_h + b$,其中 $W_x$ 是输入权重矩阵 ($D \times H$),$W_h$ 是隐藏权重矩阵 ($H \times H$),$b$ 是偏置向量 ($H$)。

第二步:解析输入格式

这道题的难点不在算法本身,而在理解输入格式。参数可能跨行排列,需要把所有数值读入一个 token 列表,按索引依次解析:

  1. 先读 $T, B, D, H$
  2. 读 $T \times B \times D$ 个浮点数作为输入序列
  3. 按顺序读 4 组门参数:输入门、遗忘门、输出门、候选细胞,每组含 $D \times H + H \times H + H$ 个参数

第三步:矩阵运算实现前向传播

$B$ 个房间通过矩阵运算批量计算——$x_t$ 的形状是 $(B, D)$,$W_x$ 是 $(D, H)$,乘积 $x_t W_x$ 形状为 $(B, H)$,恰好对所有房间并行计算。

初始化 $h_0 = 0$,$c_0 = 0$,逐时间步推进,每步按公式计算四个门和状态更新。

题解代码

import sys
import numpy as np

def sigmoid(x):
    return 1.0 / (1.0 + np.exp(-x))

def solve():
    tokens = sys.stdin.read().split()
    idx = 0

    T = int(tokens[idx]); idx += 1
    B = int(tokens[idx]); idx += 1
    D = int(tokens[idx]); idx += 1
    H = int(tokens[idx]); idx += 1

    # 读入输入序列 (T, B, D)
    X = np.zeros((T, B, D))
    for t in range(T):
        for b in range(B):
            for d in range(D):
                X[t, b, d] = float(tokens[idx]); idx += 1

    # 读取 4 个门的参数:输入门、遗忘门、输出门、候选细胞
    def read_gate():
        nonlocal idx
        Wx = np.array(tokens[idx:idx + D * H], dtype=float).reshape(D, H); idx += D * H
        Wh = np.array(tokens[idx:idx + H * H], dtype=float).reshape(H, H); idx += H * H
        b = np.array(tokens[idx:idx + H], dtype=float); idx += H
        return Wx, Wh, b

    gates = [read_gate() for _ in range(4)]
    Wxi, Whi, bi = gates[0]  # 输入门
    Wxf, Whf, bf = gates[1]  # 遗忘门
    Wxo, Who, bo = gates[2]  # 输出门
    Wxc, Whc, bc = gates[3]  # 候选细胞

    h = np.zeros((B, H))
    c = np.zeros((B, H))
    all_h = []

    for t in range(T):
        xt = X[t]
        ft = sigmoid(xt @ Wxf + h @ Whf + bf)
        it = sigmoid(xt @ Wxi + h @ Whi + bi)
        ct_tilde = np.tanh(xt @ Wxc + h @ Whc + bc)
        c = ft * c + it * ct_tilde
        ot = sigmoid(xt @ Wxo + h @ Who + bo)
        h = ot * np.tanh(c)
        all_h.append(h.copy())

    h_flat = np.concatenate(all_h).flatten()
    print(' '.join(f'{v:.4f}' for v in h_flat))
    print(' '.join(f'{v:.4f}' for v in c.flatten()), end='')

solve()

复杂度分析

时间复杂度:$O(T \cdot B \cdot (D \cdot H + H^2))$,每个时间步做 4 次矩阵乘法

空间复杂度:$O(T \cdot B \cdot H + D \cdot H + H^2)$,存储所有隐藏状态和权重矩阵


第二题:大模型预训练语料清洗

题目描述

为了防止大语言模型在生成时出现”复读机”现象,需要模拟数据清洗引擎。给定 $N$ 篇待清洗文档,按顺序执行五条清洗规则,只有全部通过的文档才会被保留:

  1. 空格规范化:将所有连续空白字符合并为一个空格,去除首尾空格。规范化后字符串长度必须在 $[L, R]$ 内,不满足则丢弃。最终输出的是规范化后的字符串。
  2. 语义单词提取:按非字母数字字符分割,提取所有有效单词,全部转为小写。
  3. 独立黑名单拦截:如果单词序列中精确匹配到任何黑名单词汇(不区分大小写),丢弃。必须是独立单词匹配,spammer 不会被黑名单中的 spam 拦截。
  4. 3-gram 复读惩罚:任何连续三个单词构成的 3-gram 出现次数严格大于 $M$ 次,丢弃。
  5. 规范化语义去重:如果两篇文档的单词序列完全一致(忽略标点和大小写),仅保留首次出现的。

输入描述

第一行 $N, L, R, M, K$,分别为文档数、最小长度、最大长度、3-gram 最大允许出现次数、黑名单词汇数。第二行 $K$ 个黑名单词汇($K=0$ 时跳过该行)。接下来 $N$ 行,每行一篇原始文档。

输出描述

按顺序输出所有通过清洗的文档,每篇占一行。

样例

输入

3 10 100 2 1
spam
Buy cheap SPAM!
He is a spammer
He is A! Spammer.

输出

He is a spammer

样例解释

  • 文档 1 Buy cheap SPAM! 规范化后长度为 15,在 $[10,100]$ 内。提取单词 [buy, cheap, spam]spam 命中黑名单,丢弃。
  • 文档 2 He is a spammer 规范化后长度 15。提取单词 [he, is, a, spammer]spammer 不等于 spam,不被拦截。3-gram 无重复。保留。
  • 文档 3 He is A! Spammer. 规范化后长度 18。提取单词 [he, is, a, spammer],与文档 2 的单词序列完全一致,语义重复,丢弃。

思路分析

第一步:逐条规则实现

这道题没有复杂的算法,核心是准确理解并实现五条清洗规则。每条规则是一个独立的过滤器,文档依次过关,任何一关不通过就丢弃。

第二步:各规则的实现技巧

  • 空格规范化:Python 的 ' '.join(doc.split()) 一行搞定——split() 不带参数会按所有空白字符分割并自动去除首尾空白
  • 单词提取:用正则 re.findall(r'[a-zA-Z0-9]+', text) 提取所有字母数字连续片段
  • 黑名单匹配:将黑名单存入 set,对每个单词判断是否 in blacklist,精确匹配不是子串匹配
  • 3-gram 计数:用字典统计每个三元组出现次数,超过 $M$ 立即跳出
  • 语义去重:将单词序列转为 tuple 作为 set 的 key,重复则跳过

第三步:注意顺序和细节

五条规则必须按顺序执行。规则 1 的规范化结果是最终输出的内容,规则 2-5 都基于规范化后的文本。特别注意 $K=0$ 时没有黑名单行需要读取。

题解代码

import sys
import re

input = sys.stdin.readline

def solve():
    first_line = input().split()
    N, L, R, M, K = int(first_line[0]), int(first_line[1]), int(first_line[2]), int(first_line[3]), int(first_line[4])

    blacklist = set()
    if K > 0:
        blacklist = set(input().split())

    seen = set()
    results = []

    for _ in range(N):
        doc = input().rstrip('\n')

        # 规则1:空格规范化
        normalized = ' '.join(doc.split())
        if not (L <= len(normalized) <= R):
            continue

        # 规则2:提取单词并转小写
        words = tuple(w.lower() for w in re.findall(r'[a-zA-Z0-9]+', normalized))

        # 规则3:黑名单独立精确匹配
        if any(w in blacklist for w in words):
            continue

        # 规则4:3-gram 复读惩罚
        if len(words) >= 3:
            trigrams = {}
            bad = False
            for i in range(len(words) - 2):
                key = (words[i], words[i + 1], words[i + 2])
                trigrams[key] = trigrams.get(key, 0) + 1
                if trigrams[key] > M:
                    bad = True
                    break
            if bad:
                continue

        # 规则5:语义去重
        if words in seen:
            continue
        seen.add(words)

        results.append(normalized)

    print('\n'.join(results))

solve()

复杂度分析

时间复杂度:$O(N \cdot W)$,$W$ 为单篇文档的平均单词数

空间复杂度:$O(N \cdot W)$,存储去重集合


小结

  • 选择题覆盖面广,从 ML/DL 基础(NMF、LDA、正则化、混淆矩阵)到前沿大模型技术(张量并行、PagedAttention、RLHF),数学题(概率、线代、数值计算)也不少,建议系统性复习
  • 第一题 LSTM 前向传播:本质是矩阵运算模拟,难点在于正确解析输入格式(参数可能跨行)和理解四个门的计算顺序。用 numpy 的矩阵乘法可以简洁实现
  • 第二题语料清洗:纯字符串模拟题,五条规则按顺序实现即可。Python 的字符串处理和正则表达式可以让实现非常简洁,关键是不要遗漏规则细节(如 $K=0$ 无黑名单行、独立匹配而非子串匹配)