华为笔试 华为笔试题 华为0318 春招实习笔试真题

笔试时间:2026年3月18日

往年笔试合集:

2023春招秋招笔试合集

2024春招秋招笔试合集

第一题:大模型训练显存优化算法

题目

在大模型训练中,为解决NPU显存不够用的情况,通常采用张量swap或者张量重计算的方式进行优化;张量swap是把张量的数据先搬到CPU,需要的时候,再从CPU搬回NPU;张量重计算是在需要张量的值时,在NPU上重新把张量的值计算出来。

假设把模型部署到NPU上,还需要 m 大小的存储空间,才能让大模型运行起来;目前有 n 个候选张量,每个张量占用一定的存储空间;n 个张量中的每个张量都可以进行swap或者重计算,swap和重计算分别对应不同的代价;试着编写一段程序,从 n 个候选张量中选择合适的张量进行swap或者重计算,在代价最小的情况下,使得大模型能够运行起来(选择的张量和大于等于 m)。

输入描述

  • 第一行为1个整数 m(0 < m < 10000),表示需要的存储空间大小
  • 第二行为1个整数 n(0 < n < 10000),表示候选张量的个数
  • 第三行有 n 个处于区间 [1, 10000] 之内的整数,表示 n 个候选张量的存储空间大小
  • 第四行有 n 个处于区间 [1, 100000] 之内的整数,表示 n 个候选张量swap的代价
  • 第五行有 n 个处于区间 [1, 100000] 之内的整数,表示 n 个候选张量重计算的代价

输出描述

如果没有找到合适的解,输出 error;否则,输出最小代价(行尾没有空格)。

样例输入

10
5
3 4 5 6 7
1 2 3 5 5
2 3 4 5 6

样例输出

6

样例说明

需要的存储空间是10;候选张量长度分别为3,4,5,6,7;张量长度组合 {3,7}、{4,6}、{4,7}、{5,6}、{5,7}、{6,7}、...都大于等于10,满足运行的基本条件;对于 {3,7} 来说,3的最小代价是1,7的最小代价是5,{3,7} 的最小代价是6,经过其他组的比较,达成目标的最小代价是6,所以输出6。

参考题解

解题思路:

本题的本质是一个变种的 0-1 背包问题。我们需要从 n 个张量中选择一部分,使得它们的空间之和 ≥ m,同时要求总代价最小。

  1. 代价转换:每个张量只能选一种优化方式(swap 或重计算),为了使总代价最小,每个张量应直接取两者的最小值:cost[i] = min(swap[i], recomp[i])
  2. 状态定义dp[j] 表示腾出至少 j 大小空间所需要的最小代价。
  3. 目标:求 dp[m]
  4. 传统的 0-1 背包通常是"不超过容量 m 的最大价值",而本题是"空间不少于 m 的最小代价"。如果选择的张量总空间 ≥ m,它同样满足运行要求。为了防止 DP 数组过大,我们将所有空间大于等于 m 的状态全部更新到 dp[m]
  5. 使用一维数组进行优化,逆序遍历防止重复选择同一张量(0-1 背包特性)。
  6. 初始化:dp[0] = 0,其余 dp[j] = INF

C++

#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;

int main() {
    int m, n;
    cin >> m >> n;

    vector<int> sizes(n), swaps(n), recomps(n);
    for (int i = 0; i < n; i++) cin >> sizes[i];
    for (int i = 0; i < n; i++) cin >> swaps[i];
    for (int i = 0; i < n; i++) cin >> recomps[i];

    // 剪枝:如果所有张量空间加起来不足 m,直接输出 error
    long long totalSize = 0;
    for (int i = 0; i < n; i++) totalSize += sizes[i];
    if (totalSize < m) {
        cout << "error" << endl;
        return 0;
    }

    // 每个张量取 swap 和重计算的最小代价
    vector<pair<int, int>> items; // (size, cost)
    for (int i = 0; i < n; i++) {
        int cost = min(swaps[i], recomps[i]);
        items.push_back({sizes[i], cost});
    }

    // 初始化 DP 数组
    const int INF = INT_MAX;
    vector<int> dp(m + 1, INF);
    dp[0] = 0;
    int maxJ = 0;

    for (auto& [s, c] : items) {
        // 0-1 背包逆序遍历
        for (int j = maxJ; j >= 0; j--) {
            if (dp[j] == INF) continue;
            int nj = j + s;
            int val = dp[j] + c;
            if (nj >= m) {
                if (val < dp[m]) dp[m] = val;
            } else {
                if (val < dp[nj]) dp[nj] = val;
            }
        }
        maxJ += s;
        if (maxJ > m) maxJ = m;
    }

    if (dp[m] == INF) {
        cout << "error" << endl;
    } else {
        cout << dp[m] << endl;
    }

    return 0;
}

Java

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int m = sc.nextInt();
        int n = sc.nextInt();

        int[] sizes = new int[n];
        int[] swaps = new int[n];
        int[] recomps = new int[n];
        for (int i = 0; i < n; i++) sizes[i] = sc.nextInt();
        for (int i = 0; i < n; i++) swaps[i] = sc.nextInt();
        for (int i = 0; i < n; i++) recomps[i] = sc.nextInt();

        // 剪枝:所有张量空间加起来不足 m,直接输出 error
        long totalSize = 0;
        for (int i = 0; i < n; i++) totalSize += sizes[i];
        if (totalSize < m) {
            System.out.println("error");
            return;
        }

        // 每个张量取 swap 和重计算的最小代价
        int[][] items = new int[n][2];
        for (int i = 0; i < n; i++) {
            items[i][0] = sizes[i];
            items[i][1] = Math.min(swaps[i], recomps[i]);
        }

        // 初始化 DP 数组
        final int INF = Integer.MAX_VALUE;
        int[] dp = new int[m + 1];
        Arrays.fill(dp, INF);
        dp[0] = 0;
        int maxJ = 0;

        for (int[] item : items) {
            int s = item[0], c = item[1];
            for (int j = maxJ; j >= 0; j--) {
                if (dp[j] == INF) continue;
                int nj = j + s;
                int val = dp[j] + c;
                if (nj >= m) {
                    if (val < dp[m]) dp[m] = val;
                } else {
                    if (val < dp[nj]) dp[nj] = val;
                }
            }
            maxJ += s;
            if (maxJ > m) maxJ = m;
        }

        if (dp[m] == INF) {
            System.out.println("error");
        } else {
            System.out.println(dp[m]);
        }
    }
}

Python

import sys
from collections import defaultdict

def solve():
    m = int(

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

2025 春招笔试合集 文章被收录于专栏

2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
正在热议
更多
# 一张图晒出你司的标语 #
4249次浏览 75人参与
# AI面会问哪些问题? #
27474次浏览 550人参与
# 开放七大实习专项,百度暑期实习值得冲吗 #
15051次浏览 221人参与
# 你的实习产出是真实的还是包装的? #
20012次浏览 342人参与
# 找AI工作可以去哪些公司? #
8924次浏览 230人参与
# 春招至今,你的战绩如何? #
64347次浏览 575人参与
# 米连集团26产品管培生项目 #
13285次浏览 285人参与
# 从事AI岗需要掌握哪些技术栈? #
8776次浏览 299人参与
# 你做过最难的笔试是哪家公司 #
33017次浏览 229人参与
# 中国电信笔试 #
31886次浏览 292人参与
# 投递几十家公司,到现在0offer,大家都一样吗 #
340689次浏览 2173人参与
# 阿里笔试 #
178341次浏览 1314人参与
# 第一份工作一定要去大厂吗 #
14380次浏览 122人参与
# 金三银四,你的春招进行到哪个阶段了? #
22046次浏览 280人参与
# 沪漂/北漂你觉得哪个更苦? #
9741次浏览 193人参与
# HR最不可信的一句话是__ #
6145次浏览 113人参与
# 应届生第一份工资要多少合适 #
20663次浏览 86人参与
# AI时代,哪个岗位还有“活路” #
11407次浏览 339人参与
# 春招你拿到offer了吗 #
831056次浏览 9986人参与
# 长得好看会提高面试通过率吗? #
22510次浏览 254人参与
# 聊聊你的职场新体验 #
336426次浏览 1895人参与
# 学历对求职的影响 #
665090次浏览 4249人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务