通过率 0% · 提交 0 · 通过 0
这道 OJ 的配套动画
旋转位置编码 · 对应本题的思路、过程和代码
旋转位置编码(Rotary Position Embedding,RoPE)通过旋转向量的方式把位置信息编码到查询向量中。给定维度为 d(d 为偶数)的向量 x[0..d-1]、底数 base 和位置 p。向量的维度两两配对:第 i 对(i 从 0 开始,共 d/2 对)由维度 (2i, 2i+1) 组成。每一对的旋转频率为 θ_i = base^(-2i/d),在位置 p 上的旋转角为 α_i = p × θ_i(弧度)。旋转规则(逆时针;每对维度按「偶数下标在前、奇数下标在后」的顺序参与计算):
y[2i] = x[2i] * cos(α_i) - x[2i+1] * sin(α_i)
y[2i+1] = x[2i] * sin(α_i) + x[2i+1] * cos(α_i)请输出旋转后的向量 y,每个分量保留 4 位小数。若某分量四舍五入到 4 位小数后为 0,输出 0.0000(不得输出 -0.0000)。
这类题属于算法机考高频题型中「位置编码 / 数值实现」方向的高频题型,通常考察对「位置编码 / 数值实现」的建模能力与边界条件处理。掌握本题的解题思路后,可举一反三应对同类真题方向,稳步提升机考通过率。
第一行三个整数 d base p。第二行 d 个实数(最多两位小数),为 x[0..d-1]。
一行 d 个数,为 y[0..d-1],每个保留 4 位小数,用单个空格分隔。
2 <= d <= 128 且 d 为偶数;2 <= base <= 100000;0 <= p <= 100000;每个分量满足 |x[j]| <= 100 且最多两位小数。测试数据保证每个输出分量距离 4 位小数的四舍五入边界足够远,任何按 IEEE 双精度浮点数计算 cos、sin 并四舍五入到 4 位小数的实现都会得到相同输出。
示例 1
输入示例
4 10000 3 1.00 0.50 -2.00 0.25
输出示例
-1.0606 -0.3539 -2.0066 0.1899
d=4 常规旋转
示例 2
输入示例
4 10000 0 3.14 -1.20 0.00 7.65
输出示例
3.1400 -1.2000 0.0000 7.6500
p=0 时旋转角为 0,输出与输入相同
时间限制 2000 ms · 内存限制 256 MB
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。
训练营动画视频讲解
登录后可查看你在本题的历史提交,以及每次的各用例通过情况。
把维度按 (2i,2i+1) 两两配对,计算 θ_i=base^(-2i/d) 和角度 α_i=pθ_i,再用同一对原始分量执行二维旋转公式。
d 为偶数,i=0..d/2-1 的配对互不重叠且覆盖全部维度。每一对严格乘以题目给定的旋转矩阵,因此拼接所有旋转对后就是完整 RoPE 结果。
时间复杂度 O(d),输出数组占用 O(d) 空间。
p=0 时角度全为 0,输出应与输入相同;计算第二个分量前不能覆盖第一个原值,格式化前要消除负零。
import math
import sys
def fmt4(y: float) -> str:
r = math.floor(y * 1e4 + 0.5) if y >= 0 else math.ceil(y * 1e4 - 0.5)
if r == 0:
r = 0
return f"{r / 10000.0:.4f}"
def solve() -> None:
data = sys.stdin.read().split()
if not data:
return
it = iter(data)
d = int(next(it)); base = float(next(it)); p = float(next(it))
xs = [float(next(it)) for _ in range(d)]
out = [""] * d
for i in range(d // 2):
theta = base ** (-2.0 * i / d)
a = p * theta
c, s = math.cos(a), math.sin(a)
x0, x1 = xs[2 * i], xs[2 * i + 1]
out[2 * i] = fmt4(x0 * c - x1 * s)
out[2 * i + 1] = fmt4(x0 * s + x1 * c)
sys.stdout.write(" ".join(out) + "\n")
solve()