蚂蚁笔试 蚂蚁笔试题 20260315 春招实习笔试真题

笔试时间:2026年3月15日

往年笔试合集:

2023春招秋招笔试合集

2024春招秋招笔试合集

第一题:木棍搭房子

题目

小明想用木棍搭一个"房子"形状:下部是一个长方形,上部是一个等腰三角形,且两者共用一条边(即长方形的上边同时作为三角形的底边,三角形除底边外的两条边要相等)。他手上有一堆木棍(每根木棍的长度为正整数),每根木棍最多使用一次。请你判断,是否能从中挑出若干根,恰好拼成这样的"房子"。

输入描述

输入一行一个整数 n (6 ≤ n ≤ 10^5),表示木棍数量。

输入第二行包含 n 个整数 a₁, a₂, …, aₙ (1 ≤ aᵢ ≤ 10^5),表示每根木棍的长度。

输出描述

输出一行:若能用这些木棍拼出"房子",输出 YES;否则输出 NO。

样例输入1

6
4 4 3 3 5 5

样例输出1

YES

样例说明1

可取两根 4 作为长方形上下边,其中上边与三角形底边共用一根、两根 3 作为长方形左右边、两根 5 作为等腰三角形的两腰。

样例输入2

6
4 4 3 3 2 1

样例输出2

NO

参考题解

解题思路:

假设我们随便找到了 3 对木棍,把它们的长度从小到大排列:A ≤ B ≤ C。我们把最长的一对 C 拿去做两腰,把最短的一对 A 拿去做底边。因为 C ≥ A,且木棍长度都是正数,所以 2C > A 永远成立(等腰三角形条件)。

最终结论:只要统计木棍出现的频率,算出总共有多少对(每 2 根算 1 对)。只要对数 ≥ 3,直接输出 YES;凑不够 3 对,输出 NO。

C++

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

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

    int n;
    if (cin >> n) {
        vector<int> counts(100005, 0);
        for (int i = 0; i < n; ++i) {
            int a;
            cin >> a;
            counts[a]++;
        }

        int total_pairs = 0;
        for (int i = 1; i <= 100000; ++i) {
            total_pairs += counts[i] / 2;
        }

        if (total_pairs >= 3) {
            cout << "YES\n";
        } else {
            cout << "NO\n";
        }
    }
    return 0;
}

Java

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

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().trim());
        int[] counts = new int[100005];

        StringTokenizer st = new StringTokenizer(br.readLine());
        for (int i = 0; i < n; i++) {
            int a = Integer.parseInt(st.nextToken());
            counts[a]++;
        }

        int totalPairs = 0;
        for (int i = 1; i <= 100000; i++) {
            totalPairs += counts[i] / 2;
        }

        System.out.println(totalPairs >= 3 ? "YES" : "NO");
    }
}

Python

import sys
from collections import Counter

input = sys.stdin.readline

def solve():
    n = int(input())
    a = list(map(int, input().split()))
    cnt = Counter(a)

    total_pairs = 0
    for v in cnt.values():
        total_pairs += v // 2

    print("YES" if total_pairs >= 3 else "NO")

solve()

第二题:好的二元组

题目

给定一个长度为 n 的数组 {a₁, a₂, …, aₙ},初始时,对于所有 1 ≤ i ≤ n 均有 aᵢ = i。定义一对二元组(有序对)(i, j) 满足 1 ≤ i, j ≤ n,i ≠ j;若 aᵢ ≤ m 且 aⱼ > m,则称 (i, j) 是一个好的二元组。

你可以进行如下操作任意次(包括 0 次):选择一个下标 i,将 aᵢ 修改为 n − aᵢ + 1。

请计算在最优操作后,数组中最多能有多少个不同的好的二元组。

输入描述

每个测试文件均包含多组测试数据。第一行输入一个整数 T (1 ≤ T ≤ 10^4) 表示数据组数,每组测试数据描述如下:

一行输入两个整数 n, m (1 ≤ n, m ≤ 10^9) 表示数组长度与阈值。

输出描述

对于每一组测试数据,新起一行,输出一个整数,表示在最优操作后,最多存在的不同好的二元组数量。

样例输入

4
5 2
4 1
1 1
3 10

样例输出

6
4
0
0

样例说明

对于第二组测试数据初始数组为 {1,2,3,4},选择下标 4,数组变为 {1,2,3,1}。此时数组满足条件的二元组有 (1,2), (1,3), (4,2), (4,3)。

可以证明不存在其他操作使得满足条件的二元组数量更多。

参考题解

解题思路:

一个好的二元组必须由一个 ≤ m 的数和一个 > m 的数配对。假设最终数组里有 A 个数 ≤ m,那么剩下的 n - A 个数就必然 > m,二元组的总对数就是 A × (n - A)。根据数学常识,当两数之和(n)固定时,要想让它们的乘积最大,A 必须尽可能接近 n / 2。

对于任意位置 i,它的值只能在 i 和 n - i + 1 之间二选一。这说明 A 的数量有一个固定的范围 [A_min, A_max]:

  • 求 A_min(必须 ≤ m 的保底个数):如果某对选项 i 和 n - i + 1 两个都 ≤ m,那无论怎么操作,最终结果肯定 ≤ m,这决定了 A 的下限。
  • 求 A_max(可能 ≤ m 的极限个数):如果某对选项中至少有一个 ≤ m,我们就贪心地全选 ≤ m 的那个,这决定了 A 的上限。

拿到取值范围 [A_min, A_max] 后,在这个闭区间里找一个最接近中点 n / 2 的合法整数,作为最终的最优 A。

C++

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

void solve() {
    long long n, m;
    cin >> n >> m;

    long long A_min = max(0LL, min(n, 2LL * m

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

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

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

全部评论

相关推荐

LLM&nbsp;Agent&nbsp;系统的核心瓶颈是上下文管理,其核心痛点包括&nbsp;Token&nbsp;限制导致的上下文溢出、多轮对话漂移、工具调用引发的上下文爆炸与污染、记忆检索不精准、记忆冲突及长任务无法持续等问题。解决方案以&nbsp;“记忆分层、上下文压缩、智能检索”&nbsp;为核心,通过滑动窗口保留近期对话、上下文总结压缩冗余信息、RAG&nbsp;实现精准记忆召回、分层记忆架构区分短期&nbsp;/&nbsp;长期&nbsp;/&nbsp;任务记忆,搭配上下文排序与工具输出压缩等技术,构建以&nbsp;Context&nbsp;Manager&nbsp;为核心的生产级架构,同时通过&nbsp;Prompt&nbsp;Budget&nbsp;规划、定期总结等最佳实践,在有限&nbsp;Token&nbsp;内为&nbsp;LLM&nbsp;提供最有价值的上下文,支撑&nbsp;Agent&nbsp;稳定高效运行。一、核心痛点1.Token上限限制,长对话+工具数据易致上下文溢出2.多轮对话漂移,Agent偏离初始任务目标3.上下文污染/爆炸,工具返回大量冗余原始数据4.记忆检索不精准,易召回无关/遗漏关键信息5.记忆无一致性机制,用户信息易出现冲突6.长周期任务无法持续推进二、核心解决原则记忆分层、上下文压缩、智能检索,用最少Token为LLM提供高价值上下文。三、核心解决方案1.滑动窗口:保留最近N轮对话,基础兜底方案2.上下文压缩:LLM定期总结对话历史,精简Token3.RAG记忆检索:按需向量检索,仅传入相关长期记忆4.分层记忆架构:短期(近期对话)+长期(用户信息)+情景(任务总结)5.上下文排序:按相关性×新鲜度×重要性打分,仅取Top&nbsp;K高价值内容6.工具输出压缩:原始数据经压缩后,仅传入核心要点四、生产级核心架构以Context&nbsp;Manager为核心统筹,形成闭环:输入层(用户查询/工具结果/历史/记忆)→核心管理层(五大解决方案模块)→记忆层(分层架构)→输出层(Prompt&nbsp;Builder按Token预算拼Prompt入LLM)→反馈层(LLM输出反向更新记忆)五、生产落地最佳实践1.提前规划各组件Token预算,避免溢出2.工具输出、记忆使用必须做压缩/检索,杜绝原始/全量数据3.每10-20轮对话定期总结,更新情景记忆4.所有上下文必经排序筛选,保留高价值内容六、未来发展方向Context&nbsp;OS、知识图谱式Graph&nbsp;Memory、自适应上下文、支撑长周期任务的Long-Term&nbsp;Agents七、核心结论LLM&nbsp;Agent的核心瓶颈是上下文管理,而非模型本身;管理本质是平衡信息完整性与Token经济性,生产落地关键是以Context&nbsp;Manager为核心,组合各类技术形成标准化处理流程。
AI求职实录
点赞 评论 收藏
分享
评论
点赞
1
分享

创作者周榜

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