【秋招笔试】2025.09.11蚂蚁秋招研发岗笔试真题改编

✅ 秋招备战指南 ✅

💡 学习建议:

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

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

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

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

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

蚂蚁

题目一:音乐节奏调节器

1️⃣:枚举所有可能的差值 d,计算每种情况的最小代价

2️⃣:对每个位置选择距离原值最近的合法目标值

3️⃣:使用数学分析优化,时间复杂度 O(n²)

难度:中等

这道题目的关键在于理解"和谐序列"的数学定义,通过枚举差值 d 并为每个位置选择最优目标值来求解。需要掌握约束优化的基本思想,以及如何在多个可选方案中选择最优解。

题目二:密码破解器

1️⃣:生成所有可能的数位排列组合

2️⃣:筛选有效排列(无前导零,不等于原数)

3️⃣:使用欧几里得算法计算最大公约数进行判断

难度:中等偏难

这道题目结合了组合数学和数论知识,需要熟练掌握排列生成算法和 GCD 计算。通过全排列枚举配合数学验证,考查了算法设计的综合能力和数学基础。

题目三:魔法数字转换器

1️⃣:利用 next_permutation 算法生成所有排列

2️⃣:使用哈希表去重,避免重复计算

3️⃣:应用数论中的互质判断,寻找公因子关系

难度:中等偏难

与题目二类似的数位重排问题,但更加注重算法优化和实现细节。需要理解排列算法的原理,掌握去重技巧,以及数论中最大公约数的高效计算方法。

01. 音乐节奏调节器

问题描述

K 小姐正在开发一个音乐节奏调节器,用来调整音乐的节拍模式。她有一个长度为 的节拍序列 ,每个 表示第 个位置的节拍强度。

K 小姐认为一个节拍序列是"和谐的",当且仅当对于任意位置 ,都有 的值相同。换句话说,每个位置的节拍强度与其位置编号的差值的绝对值必须保持一致。

现在 K 小姐可以对任意位置的节拍强度进行微调,每次可以将某个位置的值增加 或减少 。请帮助她计算出,将给定的节拍序列调整为和谐序列所需要的最少调整次数。

输入格式

第一行包含一个正整数 ,表示节拍序列的长度。

第二行包含 个正整数 ,表示初始的节拍序列。

输出格式

输出一个整数,表示将给定序列调整为和谐序列所需的最少操作次数。

样例输入

3
3 2 1
3
1 2 3

样例输出

2
0

数据范围

样例 解释说明
样例1 对于序列 [3,2,1],可以调整为 [2,2,2],此时每个位置都满足 $
样例2 序列 [1,2,3] 已经满足和谐条件($

题解

这道题的关键在于理解什么是"和谐序列"。对于一个和谐序列,所有位置的 值都相等,我们把这个相等的值记为

分析一下,对于位置 和固定的差值 ,满足 只能是两个值:。但是还有一个限制条件,就是 必须在合理范围内(通常是正整数)。

所以解题思路是:

  1. 枚举所有可能的差值 (从
  2. 对于每个 ,计算将数组调整为满足该差值的最小代价
  3. 对于每个位置 ,在可选的目标值中选择与原值 最接近的那个
  4. 取所有可能的 中代价最小的作为答案

具体来说:

  • 对于位置 和差值 ,可能的目标值有:(如果 )和 (如果
  • 在这些可能值中,选择与 差值最小的,累加到总代价中

时间复杂度是 ,对于 的数据范围完全可以接受。

参考代码

Python

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

n = int(input())
a = [0] + list(map(int, input().split()))  # 1-indexed

def solve():
    ans = float('inf')
    
    # 枚举所有可能的差值 d
    for d in range(n + 1):
        cost = 0
        valid = True
        
        for i in range(1, n + 1):
            # 计算位置 i 的可选目标值
            options = []
            if i - d >= 1:
                options.append(i - d)
            if i + d <= n:
                options.append(i + d)
            
            if not options:  # 无合法目标值
                valid = False
                break
                
            # 选择与原值最接近的目标值
            min_cost = min(abs(a[i] - opt) for opt in options)
            cost += min_cost
        
        if valid:
            ans = min(ans, cost)
    
    return ans

print(solve())

C++

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n;
    cin >> n;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    
    long long ans = LLONG_MAX;
    
    // 枚举所有可能的差值 d
    for (int d = 0; d <= n; d++) {
        long long cost = 0;
        bool ok = true;
        
        for (int i = 1; i <= n; i++) {
            long long min_cost = LLONG_MAX;
            
            // 检查 i - d 是否合法
            if (i - d >= 1) {
                min_cost = min(min_cost, (long long)abs(a[i] - (i - d)));
            }
            
            // 检查 i + d 是否合法
            if (i + d <= n) {
                min_cost = min(min_cost, (long long)abs(a[i] - (i + d)));
            }
            
            if (min_cost == LLONG_MAX) {
                ok = false;
                break;
            }
            
            cost += min_cost;
        }
        
        if (ok) {
            ans = min(ans, cost);
        }
    }
    
    cout << ans << "\n";
    return 0;
}

Java

import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        int n = Integer.parseInt(br.readLine());
        String[] tokens = br.readLine().split(" ");
        int[] a = new int[n + 1];
        for (int i = 1; i <= n; i++) {
            a[i] = Integer.parseInt(tokens[i - 1]);
        }
        
        long ans = Long.MAX_VALUE;
        
        // 枚举所有可能的差值 d
        for (int d = 0; d <= n; d++) {
            long cost = 0;
            boolean isValid = true;
            
            for (int i = 1; i <= n; i++) {
                long minCost = Long.MAX_VALUE;
                
                // 检查 i - d 是否合法
                if (i - d >= 1) {
                    minCost = Math.min(minCost, Math.abs(a[i] - (i - d)));
                }
                
                // 检查 i + d 是否合法
                if (i + d <= n) {
                    minCost = Math.min(minCost, Math.abs(a[i] - (i + d)));
                }
                
                if (minCost == Long.MAX_VALUE) {
                    isValid = false;
                    break;
                }
                
                cost += minCost;
            }
            
            if (isValid) {
                ans = Math.min(ans, cost);
            }
        }
        
        System.out.println(ans);
    }
}

02. 密码破解器

问题描述

A 先生是一名密码学专家,他正在研究一种特殊的密码系统。在这个系统中,给定一个数字密码 ,可以通过重新排列其各位数字来生成新的密码变体。

但是,生成的新密码必须满足以下条件:

  • 不能有前导零(即首位不能是 0)

  • 新密码不能与原密码 完全相同

A 先生发现,如果两个密码 的最大公约数 ,那么它们可能具有某种数学上的关联性,这对于密码分析来说是有价值的。

现在,请帮助 A 先生计算:通过重新排列数字密码 的各位数字,能够生成多少个满足条件的新密码 ,使得

注: 表示 的最大公约数,即两个数共有约数中最大的一个。

输入格式

输入一行包含一个正整数 ,表示原始的数字密码。

输出格式

输出一个整数,表示满足条件的新密码的数量。

样例输入

213
10
224

样例输出

5
0
2

数据范围

样例 解释说明
样例1 对于 213,可能的重排有:123, 132, 231, 312, 321。其中与 213 有公共因子的有 5 个
样例2 对于 10,唯一可能的重排是 01,但有前导零,所以结果是 0
样例3 对于 224,可能的重排有:242, 422,这两个都与 224 有公共因子

题解

这道题本质上是一个组合数学和数论的结合问题。我们需要:

  1. 生成所有可能的数位排列
  2. 筛选出合法的排列(无前导零,且不等于原数)
  3. 检查每个合法排列与原数的最大公约数

关键观察:

  • 由于 ,所以最多只有 10 位数字
  • 所有可能的排列数量最多是 ,在可接受范围内
  • 可以直接枚举所有排列,然后逐一检查

具体算法步骤:

  1. 将原数 转换为字符串,并按字典序排序
  2. 使用 next_permutation 或类似方法枚举所有不同的排列
  3. 对每个排列:
    • 检查是否有前导零,有

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

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

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

全部评论

相关推荐

评论
1
1
分享

创作者周榜

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