蚂蚁金服笔试 蚂蚁金服笔试题 0824

笔试时间:2025年8月24日

往年笔试合集:

2023春招秋招笔试合集

2024春招秋招笔试合集

第一题:牛

在一副牌中,数字 1~10 各有 4 张。发牌员先后给 Tk 与 wida 各发 5 张牌,此时牌堆还剩 30 张牌。两名玩家按照下列规则决定胜负:

若两人都无法从自己的 5 张手牌中选出 3 张牌,使得它们之和为 10 的倍数,则比较各自手牌中的最大数字,数字较大者获胜;若最大数字相同,则本局平局;

若仅有一人可以选出这样的 3 张牌,则该名玩家直接获胜;

若两人都可以选出这样的 3 张牌,则各自都选择一种方案,使得余下 2 张牌数字之和为 x 时,比较 ((x - 1) mod 10) + 1 的大小(即把 x mod 10 中的 0 视作 10),值较大者获胜;若两值相同,则本局平局。

现给出两名玩家的手牌,请判断每局比赛的结果。

输入描述

每个测试文件包含多组独立测试数据。第一行输入一个整数 T(1 ≤ T ≤ 10 的 4 次方)表示测试数据组数,每组测试数据的格式如下:

第一行输入 5 个整数 a₁,a₂,…,a₅(1 ≤ aᵢ ≤ 10),表示 Tk 的手牌;

第二行输入 5 个整数 b₁,b₂,…,b₅(1 ≤ bᵢ ≤ 10),表示 wida 的手牌。

保证输入合法:同一种数字的牌在两人手牌中的总数量不超过 4。

输出描述

对于每一组测试数据,新起一行输出比赛结果:

若 Tk 获胜,输出 Tk;

若 wida 获胜,输出 wida;

若平局,输出 emm。

样例输入

3

10 1 9 2 3

6 6 6 6 1

6 6 6 6 1

10 1 9 2 3

3 3 3 1 1

3 2 2 1 1

样例输出

Tk

wida

emm

参考题解

每人 5 张牌,若能从中挑 3 张使其和为 10 的倍数,则称“有牛”。余下两张之和 mod 10 得到牛数(0 记为 10)。规则:仅一人有牛 ⇒ 他赢;都有牛 ⇒ 比牛数,大者赢,相同平局;都无牛 ⇒ 比最大牌,大者赢,相同平局。关键观察:若存在三张和能整除 10,则余下两张的和 ≡ 总和 mod 10,因此牛数唯一由总和决定。无需枚举取最大。做法:判断是否存在三张和 %10==0;若有牛:牛数 = (总和 % 10) 或 10;若无牛:记录最大单牌;按优先级比较结果。复杂度:每手枚举 10 种三张组合,O(1)。

C++:

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

struct Stat {
    bool n; // 是否存在任意3个数之和能被10整除
    int  b; // 在满足条件的所有三元组里,剩余两个数之和的 (mod 10,0记为10) 的最大值
    int  m; // 数组最大值
};

static inline Stat f1(const array<int,5>& h) {
    Stat res{false, -1, *max_element(h.begin(), h.end())};
    int tot = 0;
    for (int x : h) tot += x;
    // 遍历所有 C(5,3) = 10 个三元组
    for (int i = 0; i < 5; ++i)
        for (int j = i + 1; j < 5; ++j)
            for (int k = j + 1; k < 5; ++k) {
                int s = h[i] + h[j] + h[k];
                if (s % 10 == 0) {
                    res.n = true;
                    int rem = tot - s;             // 剩余两个数之和
                    int v = rem % 10;
                    if (v == 0) v = 10;
                    if (v > res.b) res.b = v;
                }
            }
    return res;
}

static inline string g(const array<int,5>& a, const array<int,5>& b) {
    Stat s1 = f1(a), s2 = f1(b);
    if (s1.n && !s2.n) return "Tk";
    if (s2.n && !s1.n) return "wida";
    if (s1.n && s2.n) {
        if (s1.b > s2.b) return "Tk";
        if (s1.b < s2.b) return "wida";
        return "emm";
    }
    if (s1.m > s2.m) return "Tk";
    if (s1.m < s2.m) return "wida";
    return "emm";
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int T; 
    if (!(cin >> T)) return 0;
    while (T--) {
        array<int,5> a, b;
        for (int i = 0; i < 5; ++i) cin >> a[i];
        for (int i = 0; i < 5; ++i) cin >> b[i];
        cout << g(a, b) << '\n';
    }
    return 0;
}

Java:

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

public class Main {

    static class Stat {
        boolean n; // 是否存在三元组之和%10==0
        int b;     // 满足条件时剩余两数之和的 (mod 10,0记为10) 的最大值
        int m;     // 数组最大值
        Stat(boolean n, int b, int m) { this.n = n; this.b = b; this.m = m; }
    }

    static Stat f1(int[] h) {
        int m = Arrays.stream(h).max().orElse(Integer.MIN_VALUE);
        int tot = 0;
        for (int x : h) tot += x;

        boolean n = false;
        int best = -1;
        // 遍历所有 5C3 = 10 个三元组
        for (int i = 0; i < 5; i++) {
            for (int j = i + 1; j < 5; j++) {
                for (int k = j + 1; k < 5; k++) {
                    int s = h[i] + h[j] + h[k];
                    if (s % 10 == 0) {
                        n = true;
                        int rem = tot - s; // 剩余两数之和
                        int v = rem % 10;
                        if (v == 0) v = 10;
                        if (v > best) best = v;
                    }
                }
            }
        }
        return new Stat(n, best, m);
    }

    static String g(int[] a, int[] b) {
        Stat s1 = f1(a), s2 = f1(b);
        if (s1.n && !s2.n) return "Tk";
        if (s2.n && !s1.n) return "wida";
        if (s1.n && s2.n) {
            if (s1.b > s2.b) return "Tk";
            if (s1.b < s2.b) return "wida";
            return "emm";
        }
        if (s1.m > s2.m) return "Tk";
        if (s1.m < s2.m) return "wida";
        return "emm";
    }

    // 简单快读
    static class FS {
        BufferedInputStream in = new BufferedInputStream(System.in);
        byte[] buf = new byte[1 << 16];
        int ptr = 0, len = 0;

        int read() throws IOException {
            if (ptr >= len) {
                len = in.read(buf);
                ptr = 0;
                if (len <= 0) return -1;
            }
            return buf[ptr++];
        }
        String next() throws IOException {
            StringBuilder sb = new StringBuilder();
            int c;
            do { c = read(); } while (c <= ' ' && c != -1);
            if (c == -1) return null;
            while (c > ' ') {
                sb.append((char)c);
                c = read();
            }
            return sb.toString();
        }
        int nextInt() throws IOException { return Integer.parseInt(next()); }
    }

    public static void main(String[] args) throws Exception {
        FS fs = new FS();
        String tok = fs.next();
        if (tok == null) return;
        int T = Integer.parseInt(tok);
        StringBuilder out = new StringBuilder();
        for (int tc = 0; tc < T; tc++) {
            int[] a = new int[5];
            int[] b = new int[5];
            for (int i = 0; i < 5; i++) a[i] = fs.nextInt();
            for (int i = 0; i < 5; i++) b[i] = fs.nextInt();
            out.append(g(a, b)).append('\n');
        }
        System.out.print(out.toString());
    }
}

Python:

import sys
from itertools import combinations as cmb

def f1(h):
    n = False
    b = -1
    for c in cmb(range(5), 3):
        s = sum(h[i] for i in c)
        if s % 10 == 0:
            n = True
            r = [i for i in range(5) if i not in c]
            v = (h[r[0]] + h[r[1]]) % 10
            v = 10 if v == 0 else v
            if v > b:
                b = v
    m = max(h)
    return n, b, m

def g(a, b):
    x1, y1, z1 = f1(a)
    x2, y2, z2 = f1(b)
    if x1 and not x2:
        return "Tk"
    if x2 and not x1:
        return "wida"
    if x1 and x2:
        if y1 > y2: return "Tk"
        if y1 < y2: return "wida"
        return "emm"
    if z1 > z2: return "Tk"
    if z1 < z2: return "wida"
    return "emm"

def main():
    r = []
    t = int(sys.stdin.readline())
    for _ in range(t):
        a1 = list(map(int, sys.stdin.readline().split()))
        a2 = list(map(int, sys.stdin.readline().split()))
        r.append(g(a1, a2))
    sys.stdout.write("\n".join(r))

if __name__ == "__main__":
    main()

第二题:闪避

笨蛋同学正在一款游戏中打 boss,虽然她拥有无限血量,但她发现闪避后的反击伤害可能比直接攻击更高。

游戏共进行 n 轮操作,每轮可选以下两种操作之一:

攻击 boss,造成 aᵢ点伤害;

闪避 boss 的攻击,本轮不造成伤害,但若下轮选择攻击,则此次攻击造成 bᵢ点伤害。

输入描述

第一行输入一个整数 n(1 ≤ n ≤ 2×10 的 5 次方),表示游戏轮数;

第二行输入 n 个整数 a₁,a₂,…,aₙ(1 ≤ aᵢ ≤ 10 的 9 次方),表示每轮直接攻击伤害;

第三行输入 n 个整数 b₁,b₂,…,bₙ(1 ≤ bᵢ ≤ 10 的 9 次方),表示每轮闪避后下轮可造成的伤害。

输出描述

输出一个正整数,表示在最优操作下可造成的最大总伤害。

样例输入

6

1 1 4 5 1 4

1 9 1 9 8 1

样例输出

23

参考题解

我们可以用两个变量来维护当前的最大伤害:attack_dp[i]:在第 i 轮选择攻击所能获得的最大伤害。dodge_dp[i]:在第 i 轮选择闪避所能获得的最大伤害。然而,我们发现对于每一轮,我们只关心上一轮的状态,所以可以使用两个变量来代替整个数组,从而优化空间复杂度。我们用 x 代表在当前轮选择攻击所能获得的最大总伤害,用 y 代表选择闪避所能获得的最大总伤害。对于第 i 轮(从 1 开始计数),我们可以从第 i-1 轮的状态转移而来:在第 i 轮选择攻击:如果第 i-1 轮是攻击,那么第 i 轮只能

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

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

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

全部评论

相关推荐

秋招笔面试记录
点赞 评论 收藏
分享
09-16 18:10
门头沟学院 Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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