饿了么笔试 饿了么秋招 0912
笔试时间:2025年9月12日
往年笔试合集:
第一题
给定整数 n、m、k,请你在 n 行 m 列的网格中填入整数,使得:
- 每个格子填入的整数在 1 到 k 之间
- 每个整数恰好出现 (n*m)/k 次
- 对于每个 i (1≤i≤k),编号为 i 的格子构成的连通块(基于四相邻)是连通的
输入描述
第一行输入一个整数 t (1≤t≤500),表示测试用例数。 接下来 t 行,每行输入三个整数 n、m、k,满足 1≤n,m≤100、1≤k≤nm 且 nm 能被 k 整除。
输出描述
对于每个测试用例,输出 n 行,每行 m 个整数,表示一种满足条件的网格填充方案。
样例输入
2
2 2 2
2 4 2
样例输出
1 1
2 2
1 1 1 1
2 2 2 2
第一组输出中,1 和 2 各出现 2 次,且编号相同的格子各自构成基于 4 邻接的连通块; 第二组输出中,1 和 2 各出现 4 次,且编号相同的格子各自构成基于 4 邻接的连通块。
参考题解
解题思路:
使用蛇形遍历保证连通性。将网格按蛇形路径(第一行从左到右,第二行从右到左,交替进行)遍历,然后将整个路径分成 k 段,每段长度为 (n*m)/k,每段填充同一个数字。这样相同数字的格子必然在路径上连续,因此它们在网格中也一定是连通的。
C++:
#include <iostream>
#include <vector>
using namespace std;
void solve() {
int n, m, k;
cin >> n >> m >> k;
int cells_per_num = (n * m) / k;
vector<vector<int>> grid(n, vector<int>(m, 0));
int current_num = 1;
int count_for_current_num = 0;
for (int i = 0; i < n; i++) {
if (i % 2 == 0) {
for (int j = 0; j < m; j++) {
grid[i][j] = current_num;
count_for_current_num++;
if (count_for_current_num == cells_per_num && current_num < k) {
current_num++;
count_for_current_num = 0;
}
}
} else {
for (int j = m - 1; j >= 0; j--) {
grid[i][j] = current_num;
count_for_current_num++;
if (count_for_current_num == cells_per_num && current_num < k) {
current_num++;
count_for_current_num = 0;
}
}
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cout << grid[i][j];
if (j < m - 1) cout << " ";
}
cout << "\n";
}
}
int main() {
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
Java:
import java.util.*;
public class Main {
public static void solve(Scanner sc) {
int n = sc.nextInt();
int m = sc.nextInt();
int k = sc.nextInt();
int cellsPerNum = (n * m) / k;
int[][] grid = new int[n][m];
int currentNum = 1;
int countForCurrentNum = 0;
for (int i = 0; i < n; i++) {
if (i % 2 == 0) {
for (int j = 0; j < m; j++) {
grid[i][j] = currentNum;
countForCurrentNum++;
if (countForCurrentNum == cellsPerNum && currentNum < k) {
currentNum++;
countForCurrentNum = 0;
}
}
} else {
for (int j = m - 1; j >= 0; j--) {
grid[i][j] = currentNum;
countForCurrentNum++;
if (countForCurrentNum == cellsPerNum && currentNum < k) {
currentNum++;
countForCurrentNum = 0;
}
}
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
System.out.print(grid[i][j]);
if (j < m - 1) System.out.print(" ");
}
System.out.println();
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
for (int i = 0; i < t; i++) {
solve(sc);
}
sc.close();
}
}
Python:
import sys
def solve():
n, m, k = map(int, sys.stdin.readline().split())
cells_per_num = (n * m) // k
grid = [[0] * m for _ in range(n)]
current_num = 1
count_for_current_num = 0
for i in range(n):
if i % 2 == 0:
columns_iterator = range(m)
else:
columns_iterator = range(m - 1, -1, -1)
for j in columns_iterator:
grid[i][j] = current_num
count_for_current_num += 1
if count_for_current_num == cells_per_num and current_num < k:
current_num += 1
count_for_current_num = 0
for row in grid:
print(*row)
t = int(sys.stdin.readline())
for _ in range(t):
solve()
第二题
给定三个整数 a、b、c,你可以且必须恰好执行一次如下操作:选择一个整数 t,并将 a、b、c 中恰好一个数乘以 t。完成上述操作后,你可以对这三个数进行任意重排。请判断是否存在一种选择,使得最终得到的三个数可以重排成一个等比数列。
输入描述
每个测试文件均包含多组测试数据。第一行输入一个整数 t (1≤t≤500) 代表数组组数。 每组测试数据:在一行上输入三个整数 a,b,c (-10^9≤a,b,c≤10^9)。
输出描述
对于每一组测试数据,新起一行。若存在可行方案,输出 YES;否则输出 NO。
样例输入
4
2 3 6
1 2 3
2 4 8
5 1 25
样例输出
YES
NO
YES
YES
参考题解
解题思路:
等比数列的特点是中间项的平方等于两边项的乘积。枚举修改哪个数(a、b或c),然后检查是否存在整数t使得修改后的三个数能构成等比数列。对于每种修改情况,考虑修改后的数在等比数列中的位置(首项、中项或末项),利用等比数列的性质求出所需的t值并检查是否为整数。
C++:
#include <iostream>
#include <cmath>
using namespace std;
bool check(long long p, long long q, long long r) {
// 可能性1: q是中间项
if ((q * q) % r == 0) {
long long new_p = (q * q) / r;
if (new_p % p == 0) return true;
}
// 可能性2: r是中间项
if ((r * r) % q == 0) {
long long new_p = (r * r) / q;
if (new_p % p == 0) return true;
}
// 可能性3:
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南