阿里笔试 阿里智能信息 0516
笔试时间:2025年5月16日
往年笔试合集:
第一题
给定一个长度为n的数组a = {a1, a2, ..., an},且保证n为偶数。 从中选出一个长度为n/2的子序列b,其余元素组成子序列c,长度同样为n/2。 请你最大化 ∑(b[i] - c[i])(i从1到n/2)的值,并输出该最大值。 子序列为从原数组中删除任意个(可以为零,可以为全部)元素得到的新数组。
现在,对于给出的字符串和整数 p,请你直接输出和声!
输入描述
第一行输入一个整数n (1 ≤ n ≤ 2×10^5),表示数组长度。
第二行输入n个整数a1, a2, ..., an (-10^9 ≤ ai ≤ 10^9),表示数组a的各个元素。
输出描述
输出一个整数,表示所能获得的最大值。
样例输入
4
2 3 1 4
样例输出
4
解释: 选取b = {3, 4},c = {2, 1},此时 ∑(b[i] - c[i]) = (3 - 2) + (4 - 1) = 4。
参考题解
将数组按降序排序,取前 n/2 个元素构成 b,其余构成 c。 设 b 的和为 T,总和为 S,则 sum(b[i] - c[i]) = T - (S - T) = 2*T - S。
C++:
#include <bits/stdc++.h> using namespace std; using ll = long long; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; vector<ll> a(n); ll S = 0; for(int i = 0; i < n; i++){ cin >> a[i]; S += a[i]; } sort(a.begin(), a.end(), greater<ll>()); ll T = 0; for(int i = 0; i < n/2; i++){ T += a[i]; } cout << (2 * T - S) << "\n"; return 0; }
Java:
// Java 版本 import java.io.*; import java.util.*; 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()); long[] a = new long[n]; StringTokenizer st = new StringTokenizer(br.readLine()); long S = 0; for (int i = 0; i < n; i++) { a[i] = Long.parseLong(st.nextToken()); S += a[i]; } // 升序排序 Arrays.sort(a); // 取最大的 n/2 个元素之和 long T = 0; for (int i = n - 1; i >= n / 2; i--) { T += a[i]; } System.out.println(2 * T - S); } }
Python:
# Python 版本 import sys data = sys.stdin.read().split() n = int(data[0]) # 接下来的 n 个数 a = list(map(int, data[1:1+n])) S = sum(a) # 降序排序 a.sort(reverse=True) # 求前 n//2 个最大元素之和 T = sum(a[:n//2]) print(2 * T - S)
第二题
Tk有一个正整数n,Tk想知道有多少三元组(x, y, z) 满足x × y - z = n,其中x, y, z都为小于n的正整数。
输入描述
输入一个整数n (1 ≤ n ≤ 10^6) 如题意。
输出描述
输出一个整数表示满足条件的三元组个数。
样例输入
5
样例输出
5
解释: 满足条件的三元组有(2, 3, 1),(2, 4, 3),(3, 2, 1),(3, 3, 4),(4, 2, 3)。
参考题解
我们要求 x,y,z ∈ [1, n-1] 且 xy - z = n 等价于 z = xy - n 且 1 ≤ z ≤ n-1 即 n+1 ≤ x*y ≤ 2n-1 对于每个 x,从 ceil((n+1)/x) 到 floor((2n-1)/x) 的 y 都满足条件 并且 y 还要在 [1, n-1] 范围内 所以枚举 x,计算 ymin = max(1, ceil((n+1)/x)),ymax = min(n-1, floor((2n-1)/x)) 若 ymin ≤ ymax,则有 ymax - ymin + 1 个合法 y,对应每个 y 有唯一 z 累加所有 x 的合法个数即可。
C++:
#include <bits/stdc++.h> using namespace std; using ll = long long; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); ll n; cin >> n; ll ans = 0; for (ll x = 1; x < n; x++) { ll ymin = (n + 1 + x - 1) / x; ll ymax = (2 * n - 1) / x; ymin = max<ll>(ymin, 1); ymax = min<ll>(ymax, n - 1); if (ymin <= ymax) { ans += (ymax - ymin + 1); } } cout << ans << "\n"; return 0; }
Java:
// Java 版本 import java.io.*; import java.util.*; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); long n = Long.parseLong(br.readLine().trim()); long ans = 0; for (long x = 1; x < n; x++) { // 计算 ymin = ceil((n+1)/x) long ymin = (n + 1 + x - 1) / x; // 计算 ymax = floor((2n-1)/x) long ymax = (2 * n - 1) / x; ymin = Math.max(ymin, 1L); ymax = Math.min(ymax, n
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南