大厂真题 / 蚂蚁
蚂蚁 4.2 笔试真题 - 研发岗
本场考试概述
考试时间:2026年4月2日 考试岗位:研发岗 难度评级:中等偏难
考点分析:
- 第一题:GCD验证(难度中等)
- 第二题:按位分解+前缀和(难度中等)
- 第三题:字符串哈希(难度中等偏难)
建议策略:
- 第一题纯验证题,优先拿满分
- 第二题需要想到按位分解,找到规律后实现不难
- 第三题字符串哈希是模板知识点,提前背好模板可快速AC
第一题:也许互质序列
题目描述
给定一个长度为 n 的整数数列 a 和正整数 k,判断它是否同时满足:
- 对所有 i,gcd(a[i], a[i+1]) = 1(相邻两项互质);
- 对所有 i,gcd(a[i], a[i+k]) > 1(下标相差 k 的两项不互质);
- 对所有 i ≠ j,a[i] ≠ a[j](所有数字两两不同)。
样例
输入
3
5 2
10 21 22 39 34
4 3
10 21 22 25
5 2
2 3 5 7 11
输出
Yes
Yes
No
题解:GCD验证
本题是纯验证问题,依次检查三个条件,任一不满足立即返回 No。条件一遍历相邻对检查 gcd == 1,条件二遍历距离为 k 的对检查 gcd > 1,条件三用集合判重。
时间复杂度:O(n log V),其中 V 为最大元素值。 空间复杂度:O(n)。
import sys
from math import gcd
input = sys.stdin.readline
def solve():
n, k = map(int, input().split())
a = list(map(int, input().split()))
for i in range(n - 1):
if gcd(a[i], a[i + 1]) != 1:
return "No"
for i in range(n - k):
if gcd(a[i], a[i + k]) <= 1:
return "No"
if len(set(a)) != n:
return "No"
return "Yes"
T = int(input())
out = []
for _ in range(T):
out.append(solve())
print("\n".join(out))
第二题:按位与权值和
题目描述
给定一个长度为 n 的整数数组 a。选择一个分割点 p(1 ≤ p < n),将数组切分为前缀 B = a[1..p] 与后缀 C = a[p+1..n]。定义权值和 S(p) = Σ(B[i] & C[j]),对所有 i ∈ B, j ∈ C。选择 p 使得 S(p) 最大。
样例
输入
1
4
5 2 7 1
输出
8
题解:按位分解+前缀和
暴力枚举后双重循环求和为 O(n^2),n 可达 10^5 会超时。核心观察:b & c 逐位判断,各位之间互不影响,因此 S(p) 可拆成 27 个位分别计算再相加。
对第 b 位,一对 (i, j) 仅当两者第 b 位都为 1 时贡献 2^b。设 B 中有 cnt_B 个数第 b 位为 1,C 中有 cnt_C 个,第 b 位总贡献为 2^b × cnt_B × cnt_C。维护前缀计数从左到右枚举分割点即可。
时间复杂度:O(27n)。 空间复杂度:O(27)。
import sys
input = sys.stdin.readline
def solve():
n = int(input())
a = list(map(int, input().split()))
total = [0] * 27
for x in a:
for b in range(27):
if (x >> b) & 1:
total[b] += 1
prefix = [0] * 27
best = 0
for p in range(1, n):
for b in range(27):
if (a[p - 1] >> b) & 1:
prefix[b] += 1
val = 0
for b in range(27):
right = total[b] - prefix[b]
val += (1 << b) * prefix[b] * right
best = max(best, val)
print(best)
T = int(input())
for _ in range(T):
solve()
第三题:平方串
题目描述
给定若干字符串 s,可以在字符串的头部与尾部添加任意字符,使得新串能被分成两个相同的子串(平方串,形如 t+t)。求每个字符串最少需要添加多少字符。
样例
输入
5
abab
abc
aaaea
abe
abca
输出
0
3
3
3
2
题解:字符串哈希
设 L = len(s),目标串长度为 2k(2k ≥ L),需添加 2k - L 个字符。
判定 k 合法:目标串长 2k,两半相同意味着 s 中被两半同时覆盖的部分必须对应字符相等,等价于 s[0..L-k-1] == s[k..L-1]。两端添加的字符可自由赋值。
从 k = ⌈L/2⌉ 开始递增枚举,用字符串哈希 O(1) 比较前缀与后缀,第一个匹配的 k 给出最小添加数 2k - L。若直到 k = L-1 都不满足,取 k = L 必然合法。
时间复杂度:O(L)。 空间复杂度:O(L)。
import sys
input = sys.stdin.readline
MOD = 1_000_000_007
BASE = 131
def solve(s):
L = len(s)
h = [0] * (L + 1)
pw = [0] * (L + 1)
pw[0] = 1
for i in range(L):
h[i + 1] = (h[i] * BASE + ord(s[i])) % MOD
pw[i + 1] = pw[i] * BASE % MOD
def get_hash(l, r):
return (h[r + 1] - h[l] * pw[r - l + 1]) % MOD
for k in range((L + 1) // 2, L):
left_hash = get_hash(0, L - k - 1)
right_hash = get_hash(k, L - 1)
if left_hash == right_hash:
return 2 * k - L
return L
T = int(input())
out = []
for _ in range(T):
s = input().strip()
out.append(str(solve(s)))
print("\n".join(out))
小结
- 第一题 GCD 验证是纯验证题,依次检查三个条件即可,O(n log V) 线性通过
- 第二题按位分解 + 前缀和,将按位与的求和拆成各位独立计算,是位运算题的经典套路
- 第三题字符串哈希是模板知识点,关键在于推导出前缀与后缀匹配条件,再用哈希 O(1) 比较