【笔试刷题】携程-2026.03.12-算法岗-改编真题

✅ 春招备战指南 ✅

💡 学习建议:

  • 先尝试独立解题
  • 对照解析查漏补缺

🧸 题面描述背景等均已深度改编,做法和题目本质基本保持一致。

🍹 感谢各位朋友们的订阅,你们的支持是我们创作的最大动力

🌸 目前本专栏已经上线200+套真题改编解析,后续会持续更新的

春秋招笔试机考招合集 -> 互联网必备刷题宝典🔗

携程-2026.03.12-算法岗

这套算法岗题中,第 1、2、4 题与研发岗一致,第 3 题替换成了无监督学习流程。整体覆盖规律观察、分类讨论、机器学习工程实现,以及位运算 SOS DP 四个方向。下面按题目顺序整理四道题的完整内容。

题目1:吉祥物尾牌

问题描述

A 先生正在给一批活动吉祥物挂牌编号。

个吉祥物的尾牌编号规则很特别,它被定义为:

也就是常见的阶乘

现在 A 先生只关心这个大数的最后一位数字。给定整数 ,请输出 的个位数字。

输入格式

输入一行,一个整数

输出格式

输出一个整数,表示 的个位数字。

样例输入

3

样例输出

6

数据范围

样例 解释说明
样例1 ,所以个位数字是
若输入为 1 ,因此答案是

题解

这题真正考的不是怎么去算阶乘,而是观察个位数字什么时候会固定下来。

只要 ,那么 的乘积里一定同时包含:

  • 一个因子
  • 一个因子

,这就意味着整个乘积末尾至少会出现一个 。所以:

  • 时,答案一定是

剩下只需要处理前面几个很小的情况:

  • ,个位是

也就是说,这题根本不需要真的去做大整数乘法,只要分类讨论即可。

时间复杂度是 ,空间复杂度也是

参考代码

  • Python
import sys
input = lambda: sys.stdin.readline().strip()


def solve():
    n = int(input())

    # 当 n >= 5 时,阶乘里一定出现因子 2 和 5,
    # 所以末尾至少有一个 0。
    if n >= 5:
        print(0)
        return

    # 直接保存 1! 到 4! 的个位数字。
    last = [0, 1, 2, 6, 4]
    print(last[n])


if __name__ == "__main__":
    solve()
  • Cpp
#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    long long n;
    cin >> n;

    // n >= 5 时,n! 一定包含因子 10,个位固定为 0。
    if (n >= 5) {
        cout << 0 << '\n';
        return 0;
    }

    // 记录小范围阶乘的个位数字。
    int last[5] = {0, 1, 2, 6, 4};
    cout << last[n] << '\n';
    return 0;
}
  • Java
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        long n = Long.parseLong(br.readLine().trim());

        // 当 n >= 5 时,阶乘末尾一定出现 0。
        if (n >= 5) {
            System.out.println(0);
            return;
        }

        int[] last = {0, 1, 2, 6, 4};
        System.out.println(last[(int) n]);
    }
}

题目2:盲盒素数组装

问题描述

K 小姐正在准备一批盲盒礼包,总价值一共是

她打算把这份价值拆成若干个素数价值的小礼包,允许重复使用同一个素数。假设最终一共拆出了 个素数。

不过运营同学额外提出了一个限制:

  • 所有被选中的奇素数,也就是除 以外的素数,其数量必须是 的正整数倍;
  • 奇素数的数量不能是

在满足以上条件的前提下,K 小姐希望素数礼包的总个数 尽可能大。请输出这个最大的 ;如果不存在任何合法方案,输出 -1

输入格式

第一行输入一个整数 ,表示测试数据组数。

接下来 行,每行输入两个整数

输出格式

对于每组数据,输出一行一个整数,表示最大的素数个数;若无解,输出 -1

样例输入

4
6 2
2 1
30 4
1000000000000 1

样例输出

2
-1
13
499999999999

数据范围

样例 解释说明
样例1 的第一组 可以拆成 ,奇素数个数为 ,刚好是 的正整数倍,因此答案是
样例1 的第二组 时只能用素数 ,但奇素数个数不能为 ,所以无解。

题解

如果想让素数个数尽量多,那么就应该尽量使用最小的素数。

最小的素数是 ,次小的奇素数是 。由于题目对奇素数数量有限制,所以最优方案一定长这样:

  • 用尽可能少的奇素数去满足条件;
  • 这些奇素数全都取成最小的
  • 剩下的部分全部用 去填。

这样才会让素数总个数最大。

接下来问题就变成:奇素数最少要取多少个。

设奇素数个数是 odd

因为:

  • odd 必须是 的正整数倍;
  • 每个奇素数都是奇数,若用了 odd 个奇数,那么它们的总和奇偶性与 odd 相同;
  • 剩余部分全部由若干个 组成,因此剩余和一定是偶数;

所以 odd 必须与 同奇偶,否则剩下的数不可能完全由 填满。

于是:

  • 如果 同奇偶,那么最少取 odd = m
  • 如果 是奇数、 是偶数,那么最少取 odd = 2m
  • 如果 是偶数、 是奇数,那么无论取多少个 的倍数,奇素数个数都还是偶数,不可能与奇数的 同奇偶,因此无解。

确定了 odd 之后,还要保证最小总和不超过

因为每个奇素数最小只能是 ,所以至少需要:

若这个值已经大于 ,同样无解。

否则,剩下的部分全部补成 即可。设补了 two,那么:

总素数个数就是:

整题每组数据只需要做常数次判断,时间复杂度是 ,空间复杂度也是

参考代码

  • Python
import sys
input = lambda: sys.stdin.readline().strip()


def solve():
    t = int(input())
    out = []

    for _ in range(t):
        n, m = map(int, input().split())

        # odd 表示最少需要选多少个奇素数。
        if (n & 1) == (m & 1):
            odd = m
        elif m & 1:
            odd = 2 * m
        else:
            out.append("-1")
            continue

        # 每个奇素数最小只能取 3,先判断最小和是否超出。
        if 3 * odd > n:
            out.append("-1")
            continue

        # 剩余部分全部由 2 填充,总个数化简为 (n - odd) // 2。
        out.append(str((n - odd) // 2))

    sys.stdout.write("\n".join(out))


if __name__ == "__main__":
    solve()
  • Cpp
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using i128 = __int128_t;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int t;
    cin >> t;

    while (t--) {
        i64 n, m;
        cin >> n >> m;

        i128 odd;

        // 先求满足奇偶性的最少奇素数个数。
        if ((n & 1LL) == (m & 1LL)) {
            odd = m;
        } else if (m & 1LL) {
            odd = (i128)2 * m;
        } else {
            cout << -1 << '\n';
            continue;
        }

        // 最小奇素数都是 3,如果连最小和都放不下就无解。
        if ((i128)3 * odd > (i128)n) {
            cout << -1 << '\n';
            continue;
        }

        // 剩余都放成 2,答案可直接化简。
        i128 ans = ((i128)n - odd) / 2;
        cout << (long long)ans << '\n';
    }

    return 0;
}
  • Java
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int t = Integer.parseInt(br.readLine().trim());
        StringBuilder sb = new StringBuilder();

        for (int cs = 0; cs < t; cs++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            long n = Long.parseLong(st.nextToken());
            long m = Long.parseLong(st.nextToken());

            long odd;

            // odd 表示最少需要的奇素数个数。
            if ((n & 1L) == (m & 1L)) {
                odd = m;
            } else if ((m & 1L) == 1L) {
                odd = 2L * m;
            } else {
                sb.append(-1).append('\n');
                continue;
            }

            // 先判断最小可能的奇素数总和是否超出 n。
            if (odd > n / 3L) {
                sb.append(-1).append('\n');
                continue;
            }

            long ans = (n - odd) / 2L;
            sb.append(ans).append('\n');
        }

        System.out.print(sb);
    }
}

题目3:无监督学习流程

问题描述

在仅使用 numpy/pandas/scikit-learn 的前提下,完成如下无监督三步流程,并对测试集输出聚类标签。

  1. 预处理:对训练集与测试集的所有列,先用训练集该列均值填充 NaN;如果某一行列数不足最大列数,则缺失位置也视为 NaN。随后用 StandardScaler 在训练集上 fit,并对训练集、测试集做同一变换。
  2. 降维(PCA):选择最小的 pca_dim,使得前 pca_dim 个主成分的累计解释方差不小于 0.95。若不需要降维,则保留原始标准化后的全部维度。
  3. 选择 k:从候选集合 k_list 中枚举每个 k,在训练集上训练 KMeans(n_clusters=k, random_state=42, n_init=10),并计算训练集的 silhouette_score。若 k=1k 非法,或轮廓系数无法计算,则该 k 的得分记为 -1。取得分最高的 k_star;若并列,取较小的 k
  4. 输出测试标签:使用 k_star 在训练集上重新拟合 KMeans,并对测试集执行 predict。直接输出 KMeans 的原生标签,不再重排。

输入格式

输入为一行字典,包含以下三个键:

  • train:训练特征,形如二维数组;
  • test:测试特征,形如二维数组;
  • k_list:候选聚类数列表。

允许数组元素中出现 NaN。若不同样本的列数不一致,则按最大列数对较短样本右侧补 NaN 后再统一处理。

输出格式

输出一个字典,包含三个键:

  • pca_dim:最终选中的 PCA 维度;
  • k_star:最优聚类数;
  • test_pred:与测试集行顺序对应的整型标签列表。

样例输入

{"train":[[0.0,0.0],[0.2,0.1],[5.0,5.1],[4.9,4.8]],"test":[[0.1,NaN],[5.2,4.9]],"k_list":[2,3]}

样例输出

{"pca_dim":1,"k_star":2,"test_pred":[0,1]}

数据范围

  • 2 <= len(train) <= 200
  • 1 <= len(test) <= 200
  • 1 <= 最大列数 <= 20
  • 2 <= k <= 8
项目 说明
候选 k 不保证都合法,需要按题意把非法情况记为 -1
标签输出 直接输出 KMeans.predict 的原生标签,不做重排

题解

这题的难点不在某个单点算法,而在于三个步骤必须严格按题意衔接,否则答案很容易和标答不一致。

第一步是统一数据形状与缺失值处理。由于输入可能出现“某些样本列数更短”的情况,所以应先把所有样本补到相同列数,缺失位置都视为 。接着只用训练集统计每一

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

互联网刷题笔试宝典 文章被收录于专栏

互联网刷题笔试宝典,这里涵盖了市面上大部分的笔试题合集,希望助大家春秋招一臂之力

全部评论

相关推荐

评论
1
3
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务