【笔试刷题】蚂蚁-2026.03.15-算法岗-改编真题

✅ 春招备战指南 ✅

💡 学习建议:

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

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

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

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

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

蚂蚁-2026.03.15-算法岗

这一套前后层次很清楚:第 1 题是纯判断型热身,关键只是别被“大整数”三个字吓到;第 2 题虽然披着图学习外壳,但本质是按题面公式做一次聚合和小规模线性代数实现,属于整场最容易在细节上丢分的题;第 3 题回到经典字符串比较,真正难点是把“两端删字符”改写成固定长度窗口的最小字典序比较。

题目一:祝福乘积校验

这题本质是整除判定,不需要真的把两个超长整数乘出来。把字符串逐位对 取模后再相乘即可,做法非常直接。最容易错的地方是想当然上大整数库,结果把一个热身题写重了。

难度:简单

题目二:单层节点分类器

题面看着像机器学习,实际完全是实现题:无向图一跳均值聚合、岭回归闭式解、再接一次 sigmoid 判类。真正卡人的地方在于“自己也参与平均”“孤立点保持原向量”“浮点输出按题意保留到小数点后 6 位”这些工程细节。只要流程没有读错,这题并不需要任何额外模型知识。

难度:中等偏难

题目三:裁边后的最小片段

把左右删掉恰好 个字符后,剩下的一定是原串里的一个长度为 的连续子串,所以题目马上转成若干固定长度窗口的字典序最小值。难点不在贪心,而在怎么高效比较两个候选窗口;这里用双模哈希加二分 LCP 就够了。实现时最容易写炸的是比较函数边界和哈希下标。

难度:中等

1. 祝福乘积校验

问题描述

小基 在生日当天收到了很多朋友发来的祝福消息。第 位朋友会给出两个十进制大整数

小基 约定:如果 的倍数,就认为这份祝福通过了校验。

现在请对每位朋友分别判断,这份祝福是否通过校验。

输入格式

每个测试文件均包含多组测试数据。

第一行输入一个整数 ,表示朋友的数量。

接下来 行,每行输入两个由数字字符构成、且不含前导零的整数

输出格式

对于每位朋友,单独输出一行结果:

  • 如果 的倍数,输出 Yes
  • 否则输出 No

输出大小写必须与样例一致。

样例输入

5
2 3
6 11
22 9
25 44
121 132

样例输出

No
Yes
Yes
No
Yes

数据范围

  • 单个测试文件内,所有 的位数之和不超过

题解

这题的核心不是“大整数乘法”,而是“整除判定”。

因为只需要判断 是否是 的倍数,所以根本没有必要真的把两个超长整数乘出来。只要保留模 的结果就够了。

设:

那么:

于是只要判断:

就能得到答案。

怎么求超长整数对 取模

把数字当成字符串逐位读入。

如果当前已经处理出的前缀模值是 cur,读到新的一位数字 d 之后,新模值就是:

整段字符串扫完,就得到了这个大整数对 的模。

复杂度分析

设某组数据中两个字符串长度之和为

逐位取模只需要线性扫描,因此这一组的复杂度是

整份测试文件中,所有数字总位数不超过 ,所以总复杂度就是 ,额外空间复杂度为

参考代码

  • Python
import sys

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


def mod66(s: str) -> int:
    val = 0
    for ch in s:
        val = (val * 10 + ord(ch) - 48) % 66
    return val


def solve() -> None:
    t = int(input())
    out = []
    for _ in range(t):
        x, y = input().split()
        ok = mod66(x) * mod66(y) % 66 == 0
        out.append("Yes" if ok else "No")
    sys.stdout.write("\n".join(out))


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

int mod66(const string& s) {
    int val = 0;
    for (char ch : s) {
        val = (val * 10 + (ch - '0')) % 66;
    }
    return val;
}

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

    int T;
    cin >> T;
    while (T--) {
        string x, y;
        cin >> x >> y;
        bool ok = 1LL * mod66(x) * mod66(y) % 66 == 0;
        cout << (ok ? "Yes" : "No") << '\n';
    }
    return 0;
}
  • Java
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.StringJoiner;

public class Main {
    static int mod66(String s) {
        int val = 0;
        for (int i = 0; i < s.length(); i++) {
            val = (val * 10 + s.charAt(i) - '0') % 66;
        }
        return val;
    }

    public static void main(String[] args) throws Exception {
        FastScanner fs = new FastScanner(System.in);
        int t = fs.nextInt();
        StringBuilder sb = new StringBuilder();
        for (int cs = 0; cs < t; cs++) {
            String x = fs.next();
            String y = fs.next();
            boolean ok = (long) mod66(x) * mod66(y) % 66 == 0;
            sb.append(ok ? "Yes" : "No").append('\n');
        }
        System.out.print(sb);
    }

    static class FastScanner {
        private final InputStream in;
        private final byte[] buf = new byte[1 << 16];
        private int ptr = 0;
        private int len = 0;

        FastScanner(InputStream is) {
            in = new BufferedInputStream(is);
        }

        private 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 {
            int c;
            do {
                c = read();
            } while (c <= ' ' && c != -1);
            StringBuilder sb = new StringBuilder();
            while (c > ' ') {
                sb.append((char) c);
                c = read();
            }
            return sb.toString();
        }

        int nextInt() throws IOException {
            return Integer.parseInt(next());
        }
    }
}

2. 单层节点分类器

问题描述

小基 正在整理一张无向关系网络。图中共有 个节点,节点编号为 ,每个节点都带有一个长度为 的原始特征向量。

现在需要按照下面这套固定流程,实现一个单层 GraphSAGE-Mean 节点分类器

  1. 图是无向图,没有自环,输入给出邻接边 edges
  2. 原始特征矩阵记为
  3. 先做一跳平均聚合,得到新特征矩阵 。对于节点

如果节点 的度数为 ,那么直接有

  1. 只在训练节点上已知标签 。设训练节点对应的特征矩阵是 ,标签向量是 ,并固定 ,训练目标为:

其闭式解为:

  1. 对任意节点 ,预测概率为:

其中 。阈值取 ,若 则预测标签为 ,否则为

请输出权重向量、测试点的预测概率,以及测试点的预测标签。

输入格式

输入只有一行,是一个 JSON 对象:

{
  "nodes": [[...], [...], ...],
  "edges": [[u1, v1], [u2, v2], ...],
  "train_idx": [i1, i2, ...],
  "train_y": [0, 1, ...],
  "test_idx": [j1, j2, ...]
}

其中:

  • nodes 表示原始特征矩阵;
  • edges 表示无向边;
  • train_idx 表示训练节点下标;
  • train_y 表示训练节点标签;
  • test_idx 表示需要预测的节点下标。

输出格式

输出一行 JSON:

{
  "weights": [...],
  "test_proba": [...],
  "test_pred": [...]
}

要求:

  • weights 长度为
  • test_proba 长度等于 test_idx 的长度;
  • 所有浮点数都按照 round(x, 6) 的规则保留到小数点后 位。

样例输入

{"nodes":[[0,0],[0.2,0.1],[0.1,-0.1],[4,4],[4.2,3.9]],"edges":[[0,1],[0,2],[3,4]],"train_idx":[0,3],"train_y":[0,1],"test_idx":[1,4]}

样例输出

{"weights":[0.085354,0.164463],"test_proba":[0.50419,0.730977],"test_pred":[1,1]}

数据范围

题解

这题本质上是一道按固定公式实现的题,关键是不要把流程理解错。

第一步:做一跳均值聚合

先按无向图建邻接表。

然后对每个节点 ,把自己和所有一跳邻居的特征向量加起来,再除以 ,就得到新的特征向量

这里有两个容易错的点:

  • 这一步是自己也要参与平均,不是只平均邻居。
  • 图是无向图,所以每条边要双向加入。

第二步:只在训练节点上做岭回归

题目已经把目标函数和闭式解都写出来了,所以不需要再去训练什么神经网络,也不需要自己迭代梯度下降。

把训练节点对应的那些行抽出来,记成矩阵 ,再把标签写成列向量

接着计算:

问题就变成了解线性方程:

由于 ,直接用高斯消元就够了。

第三步:算概率并判类

拿到 以后,对测试节点 计算:

如果 ,预测标签就是 ,否则是

为什么这样做是对的

因为题目已经明确规定了:

  1. 特征如何聚合;
  2. 训练目标函数是什么;
  3. 闭式解怎么写;
  4. 预测时如何从线性结果映射到概率。

所以只要严格按这套流程实现,得到的结果就是题目要求的标准答案。

复杂度分析

设节点数为 ,特征维度为 ,边数为

  • 建图和聚合的复杂度是
  • 计算 的复杂度是
  • 解一个 的线性方程组,复杂度是

由于本题 都很小,所以整体代价非常低。

参考代码

  • Python
import json
import math
import sys

input = lambda: sys.stdin.readline().strip()
LAMBDA = 0.01


def sigmoid(x: float) -> float:
    if x >= 0:
        e = math.exp(-x)
        return 1.0 / (1.0 + e)
    e = math.exp(x)
    return e / (1.0 + e)


def gauss(a, b):
    n = len(a)
    for col in range(n):
        pivot = col
        for row in range(col, n):
            if abs(a[row][col]) > abs(a[pivot][col]):
                pivot = row
        a[col], a[pivot] = a[pivot], a[col]
        b[col], b[pivot] = b[pivot], b[col]

        base = a[col][col]
        for j in range(col, n):
            a[col][j] /= base
        b[col] /= base

        for row in range(n):
            if row == col:
                continue
            fac = a[row][col]
            if abs(fac) < 1e-12:
                continue
            for j in range(col, n):
                a[row][j] -= fac * a[col][j]
            b[row] -= fac * b[col]
    return b


def solve() -> None:
    data = json.loads(input())
    nodes = data["nodes"]
    edges = data["edges"]
    train_idx = data["train_idx"]
    train_y = data["train_y"]
    test_idx = data["test_idx"]

    n = len(nodes)
    d = len(nodes[0])
    g = [[] for _ in range(n)]
    for u, v in edges:
        g[u].append(v)
        g[v].append(u)

    h = [[0.0] * d for _ in range(n)]
    for i in range(n):
        cnt = len(g[i]) + 1
        for k in range(d):
            cur = nodes[i][k]
            for v in g[i]:
                cur += nodes[v][k]
            h[i][k] = cur / cnt

    a = [[0.0] * d for _ in range(d)]
    b = [0.0] * d
    for idx, y in zip(train_idx, train_y):
        row = h[idx]
        for i in range(d):
            b[i] += row[i] * y
            for j in range(d):
                a[i][j] += row[i] * row[j]
    for i in range(d):
        a[i][i] += LAMBDA

    w = gauss(a, b)
    proba = []
    pred = []
    for idx in test_idx:
        z = 0.0
        for i in range(d):
            z += h[idx][i] * w[i]
        p = sigmoid(z)
        proba.append(round(p, 6))
        pred.append(1 if p >= 0.5 else 0)

    ans = {
        "weights": [round(x, 6) for x in w],
        "test_proba": proba,
        "test_pred": pred,
    }
    sys.stdout.write(json.dumps(ans, ensure_ascii=False, separators=(",", ":")))


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

const double LAMBDA = 0.01;

struct Parser {
    string s;
    int p = 0;

    explicit Parser(string str) : s(std::move(str)) {}

    void skip() {
        while (p < (int)s.size() && isspace((unsigned char)s[p])) {
            ++p;
        }
    }

    void expect(char c) {
        skip();
        if (p >= (int)s.size() || s[p] != c) {
            throw runtime_error("parse error");
        }
        ++p;
    }

    bool eat(char c) {
        skip();
        if (p < (int)s.size() && s[p] == c) {
            ++p;
            return true;
        }
        return false;
    }

    string parseString() {
        skip();
        expect('"');
        string res;
        while (p < (int)s.size() && s[p] != '"') {
            res.push_back(s[p++]);
        }
        expect('"');
        return res;
    }

    double parseNumber() {
        skip();
        int st = p;
        if (s[p] == '-') {
            ++p;
        }
        while (p < (int)s.size() && isdigit((unsigned char)s[p])) {
            ++p;
        }
        if (p < (int)s.size() && s[p] == '.') {
            ++p;
            while (p < (int)s.size() && isdigit((unsigned char)s[p])) {
                ++p;
            }
        }
        return stod(s.substr(st, p - st));
    }

    vector<double> parseDoubleArray() {
        vector<double> res;
        expect('[');
        if (eat(']')) {
            return res;
        }
        while (true) {
            res.push_back(parseNumber());
            if (eat(']')) {
                break;
            }
            expect(',');
        }
        return res;
    }

    vector<int> parseIntArray() {
        vector<int> res;
        expect('[');
        if (eat(']')) {
            return res;
        }
        while (true) {
            res.push_back((int)llround(parseNumber()));
            if (eat(']')) {
                break;
            }
            expect(',');
        }
        return res;
    }

    vector<vector<double>> parseDoubleMatrix() {
        vector<vector<double>> res;
        expect('[');
        if (eat(']')) {
            return res;
        }
        while (true) {
            res.push_back(parseDoubleArray());
            if (eat(']')) {
                break;
            }
            expect(',');
        }
        return res;
    }

    vector<vector<int>> parseIntMatrix() {
        vector<vector<int>> res;
        expect('[');
        if (eat(']')) {
            return res;
        }
        while (true) {
            res.push_back(parseIntArray());
            if (eat(']')) {
                break;
            }
            expect(',');
        }
        return res;
    }
};

double sigmoid(double x) {
    if (x >= 0) {
        double e = exp(-x);
        return 1.0 / (1.0 + e);
    }
    double e = exp(x);
    return e / (1.0 + e);
}

vector<double> gauss(vector<vector<double>> a, vector<double> b) {
    int n = (int)a.size();
    for (int col = 0; col < n; ++col) {
        int pivot = col;
        for (int row = col; row < n; ++row) {
            if (fabs(a[row][col]) > fabs(a[pivot][col])) {
                pivot = row;
            }
        }
        swap(a[col], a[pivot]);
        swap(b[col], b[pivot]);

        double base = a[col][col];
        for (int j = col; j < n; ++j) {
            a[col][j] /= base;
        }
        b[col] /= base;

        for (int row = 0; row < n; ++row) {
            if (row == col) {
                continue;
            }
            double fac = a[row][col];
            if (fabs(fac) < 1e-12) {
                continue;
            }
            for (int j = col; j < n; ++j) {
                a[row][j] -= fac * a[col][j];
            }
            b[row] -= fac * b[col];
        }
    }
    return b;
}

string fmt(double x) {
    double y = round(x * 1e6) / 1e6;
    if (fabs(y) < 5e-13) {
        y = 0.0;
    }
    ostringstream oss;
    oss << fixed << setprecision(6) << y;
    string s = oss.str();
    while (!s.empty() && s.back() == '0') {
        s.pop_back();
    }
    if (!s.empty() && s.back() == '.') {
        s += '0';
    }
    if (s.empty() || s == "-0") {
        s = "0.0";
    }
    if (s.find('.') == string::npos) {
        s += ".0";
    }
    return s;
}

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

    string line, tmp;
    while (getline(cin, tmp)) {
        line += tmp;
    }

    Parser ps(line);
    vector<vector<double>> nodes;
    vector<vector<int>> edges;
    vector<int> trainIdx, trainY, testIdx;

    ps.expect('{');
    while (true) {
        string key = ps.parseString();
        ps.expect(':');
        if (key == "nodes") {
            nodes = ps.parseDoubleMatrix();
        } else if (key == "edges") {
            edges = ps.parseIntMatrix();
        } else if (key == "train_idx") {
            trainIdx = ps.parseIntArray();
        } else if (key ==

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

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

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

全部评论

相关推荐

昨天 18:04
已编辑
西安交通大学 Java
我是菜鸡。4道题一道都没有全对,0.95&nbsp;&nbsp;0.4&nbsp;&nbsp;0.975&nbsp;&nbsp;0.95&nbsp;&nbsp;与大厂无缘了不愧是拼都督,笔试都能感觉到卷了--------第二题的屎山代码import&nbsp;java.util.*;import&nbsp;java.io.*;public&nbsp;class&nbsp;Main{public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;throws&nbsp;InterruptedException&nbsp;{Scanner&nbsp;sc=new&nbsp;Scanner(new&nbsp;BufferedInputStream(System.in));PrintWriter&nbsp;out=new&nbsp;PrintWriter(new&nbsp;BufferedOutputStream(System.out));int&nbsp;L=sc.nextInt(),C=sc.nextInt(),n=sc.nextInt();int[]ds=new&nbsp;int[n+1];int[]ps=new&nbsp;int[n+1];for(int&nbsp;i=0;i&lt;n;i++){ds[i]=sc.nextInt();ps[i]=sc.nextInt();}ds[n]=L;ArrayDeque&lt;Integer&gt;w=new&nbsp;ArrayDeque&lt;&gt;();int&nbsp;next=C;int&nbsp;start=-1;int&nbsp;startC=C;long&nbsp;cost=0;boolean&nbsp;stop=false;for(int&nbsp;i=0;i&lt;=n;i++){if(next&gt;=ds[i]){while(!w.isEmpty()&amp;&amp;ps[w.getLast()]&gt;=ps[i])w.removeLast();w.addLast(i);}else{int&nbsp;need=ds[i]-next;while(!w.isEmpty()&amp;&amp;need&gt;0){int&nbsp;idx=w.getFirst();int&nbsp;space=(C-startC)+(ds[idx]-(start==-1?0:ds[start]));//&nbsp;可以加的油=邮箱中剩余的空间=起点时邮箱不满的空间+从起点走到这里花的油if(space&lt;=need){need-=space;next+=space;cost+=(long)space*ps[idx];startC=C;start=idx;w.removeFirst();}else{start=idx;startC=C-space+need;next+=need;cost+=(long)need*ps[idx];need=0;}}if(need&gt;0){stop=true;break;}i--;&nbsp;//&nbsp;这时候反悔加了油,但是当前的i处的加油站还没有加进来,再来一轮}}if(stop)out.println(-1);else&nbsp;out.println(cost);out.flush();out.close();sc.close();}}只记得样例1了20&nbsp;10&nbsp;34&nbsp;59&nbsp;215&nbsp;6输出为24
拼多多集团-PDD笔试
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

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