小红书笔试 小红书笔试题 0813
笔试时间:2025年8月13日
往年笔试合集:
第一题:超级重排
Tk 有一个长度为 n 的数组{a1,a2,...,an}。Tk 定义这个数组的权值为:。为了使数组的权值最大,Tk 提出如下超级重排流程:·将所有元素的十进制表示按原序拼接成一个字符串;·对该字符串中的所有字符进行重新排列;·按照原元素的位数切分字符串,恢复为 n 个新数字。或者换句话说,首先,收集所有数字的每一个单独的数位;其次,对于每一个原始数字 ai,记录下它的位数。你必须用收集到的所有数位来构造 n 个新的数字,其中第 j 个新数字的位数必须与原始数组中第 j 个数字 aj 的位数相同。你的目标是找到一种分配这些数位的方式,使得这 n 个新数字的总和达到最大。
输入描述
第一行输入一个整数 n(1≤n≤2*105),表示数组长度。
第二行输入 n 个整数a1,a2,...,an(1≤ai≤109)表示数组 a,题目保证每个元素的十进制表示中不含字符 '0'
输出描述
输出一个整数,表示经过超级重排后数组的最大权值。
样例输入
2
36 15
样例输出
114
参考题解
每个位置的权重是 10^e,其中 e 是它到右端的距离(个位 e=0,十位 e=1,百位 e=2…)。所有数字的位数是固定的,所以每个原数字的高位权重大,低位权重小。最优策略:把所有位置(带权重的格子)统一考虑,按权重从大到小分配最大的数字(重排不等式)。记录位数统计每个 ai 的位数 Li。统计所有数字字符例如 [36,15] [36, 15] [36,15] → [3, 6, 1, 5]。统计每个位置的权重如果一个数字的长度是 L,它的位权分别是:10^{L-1}, 10^{L-2}, ....., 10^0把所有数字的位权放到一个“权重桶”里。排序匹配将权重从大到小排序。将数字字符从大到小排序。一一对应,最大数字放到最大权重位置。计算总和不需要真正构造新数字,只要累加:贡献=数字×位权。
C++:
#include <bits/stdc++.h> #include <boost/multiprecision/cpp_int.hpp> using namespace std; using boost::multiprecision::cpp_int; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; if (!(cin >> n)) return 0; if (n <= 0) { cout << 0 << "\n"; return 0; } vector<string> tokens; tokens.reserve(n); for (int i = 0; i < n; ++i) { string tok; cin >> tok; tokens.push_back(tok); } int maxL = 0; vector<long long> digit_cnt(10, 0); vector<int> lens; lens.reserve(n); for (auto &tok : tokens) { int L = (int)tok.size(); lens.push_back(L); maxL = max(maxL, L); for (char ch : tok) { int d = ch - '0'; ++digit_cnt[d]; } } // len_cnt[L] = count of tokens with length == L vector<long long> len_cnt(maxL + 1, 0); for (int L : lens) ++len_cnt[L]; // suff_ge[L] = number of tokens with length >= L vector<long long> suff_ge(maxL + 2, 0); long long s = 0; for (int L = maxL; L >= 1; --L) { s += len_cnt[L]; suff_ge[L] = s; } // pow10[e] = 10^e (big integer) vector<cpp_int> pow10(maxL > 0 ? maxL : 1); pow10[0] = 1; for (int e = 1; e < maxL; ++e) pow10[e] = pow10[e - 1] * 10; cpp_int ans = 0; int d = 9; for (int e = maxL - 1; e >= 0; --e) { long long slots = suff_ge[e + 1]; while (slots > 0) { while (d >= 0 && digit_cnt[d] == 0) --d; if (d < 0) break; long long take = (long long)min<long long>(digit_cnt[d], slots); // ans += take * d * 10^e cpp_int contrib = pow10[e] * (long long)d * take; ans += contrib; digit_cnt[d] -= take; slots -= take; } } cout << ans << "\n"; return 0; }
Java:
import java.io.*; import java.math.BigInteger; import java.util.StringTokenizer; public class Main { public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String line; line = br.readLine(); if (line == null || line.trim().isEmpty()) { System.out.println(0); return; } int n = Integer.parseInt(line.trim()); if (n <= 0) { System.out.println(0); return; } StringTokenizer st = new StringTokenizer(""); String[] tokens = new String[n]; int got = 0; while (got < n) { if (!st.hasMoreTokens()) { String l = br.readLine(); if (l == null) break; st = new StringTokenizer(l); continue; } tokens[got++] = st.nextToken(); } if (got < n) { // 输入不足时按 0 处理 System.out.println(0); return; } int maxL = 0; long[] digitCnt = new long[10]; int[] lens = new int[n]; for (int i = 0; i < n; i++) { String tok = tokens[i]; int L = tok.length(); lens[i] = L; if (L > maxL) maxL = L; for (int k = 0; k < L; k++) { int d = tok.charAt(k) - '0'; digitCnt[d]++; } } long[] lenCnt = new long[maxL + 1]; for (int L : lens) lenCnt[L]++; long[] suffGe = new long[maxL + 2]; long s = 0; for (int L = maxL; L >= 1; L--) { s += lenCnt[L]; suffGe[L] = s; } BigInteger[] pow10 = new BigInteger[Math.max(1, maxL)]; pow10[0] = BigInteger.ONE; for (int e = 1; e < maxL; e++) { pow10[e] = pow10[e - 1].multiply(BigInteger.TEN); } BigInteger ans = BigInteger.ZERO; int d = 9; for (int e = maxL - 1; e >= 0; e--) { long slots = suffGe[e + 1]; while (slots > 0) { while (d >= 0 && digitCnt[d] == 0) d--; if (d < 0) break; long take = Math.min(digitCnt[d], slots); BigInteger contrib = pow10[e] .multiply(BigInteger.valueOf(d)) .multiply(BigInteger.valueOf(take)); ans = ans.add(contrib); digitCnt[d] -= take; slots -= take; } } System.out.println(ans.toString()); } }
Python:
def main(): n = int(input()) tokens = input().split() maxL = 0 len_cnt = [0] * 11 digit_cnt = [0] * 10 for tok in tokens: L = len(tok) len_cnt[L] += 1 if L > maxL: maxL = L for ch in tok: d = int(ch) digit_cnt[d] += 1 suff_ge = [0] * (maxL + 2) s = 0 for L in range(maxL, 0, -1): s += len_cnt[L] suff_ge[L] = s pow10 = [1]
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南