淘天笔试 淘天笔试题 0507
笔试时间:2025年5月7日
往年笔试合集:
第一题
Tk有一个长度为n的数组 {a1, a2, ..., an},他希望将数组分割为 {a1, a2, ..., ax} 和 {ax+1, ax+2, ..., an} 两个部分(显然,x需要满足≤ x < n),使得下式的答案达到最大: ∑(i = 1到x) ∑(j = x + 1到n) ai × aj 你并不需要告诉他具体分割位置,只需要告诉他最终结果即可。由于答案可能很大,请将答案对998244353取模后输出。
输入描述
第一行输入一个正整数n (2 ≤ n ≤ 2 × 10^5) 表示数组大小。
第二行输入n个整数a1, a2, ..., an (1 ≤ ai ≤ 10^4) 代表数组中的元素。
输出描述
输出一个值表示上式的最大值。由于答案可能很大,请将答案对998244353取模后输出。
样例输入
5
3 2 4 1 5
样例输出
54
解释: 分割最终区间为 [1, 3], [4, 5] 可以得到最大值54
参考题解
先用一次遍历算出全数组元素和 T = ∑ a[i]。 再维护一个前缀和 S=∑_{i=1}^x a[i],那么后缀和就是 T−S。 每向右移动一个分割点 x,更新 S,计算当前交叉乘积和 S*(T−S),在所有 x 中取最大值。 最后对 998244353 取模输出即可。
C++:
#include <bits/stdc++.h> using namespace std; using ll = long long; const ll MOD = 998244353; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; vector<ll> a(n); for(int i = 0; i < n; i++) cin >> a[i]; ll t = 0; for(ll x : a) t += x; ll s = 0, b = 0; for(int i = 0; i + 1 < n; i++){ s += a[i]; ll v = s * (t - s); if (v > b) b = v; } cout << (b % MOD) << "\n"; return 0; }
Java:
// Java 版本 import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; import java.util.StringTokenizer; public class Main { static final long MOD = 998244353L; public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st; int n = Integer.parseInt(br.readLine()); st = new StringTokenizer(br.readLine()); long[] a = new long[n]; for (int i = 0; i < n; i++) { a[i] = Long.parseLong(st.nextToken()); } long t = 0; for (long x : a) { t += x; } long s = 0, b = 0; for (int i = 0; i + 1 < n; i++) { s += a[i]; long v = s * (t - s); if (v > b) { b = v; } } System.out.println(b % MOD); } }
Python:
# Python 版本 import sys input = sys.stdin.readline MOD = 998244353 def main(): n = int(input()) a = list(map(int, input().split())) t = sum(a) s = 0 b = 0 for i in range(n - 1): s += a[i] v = s * (t - s) if v > b: b = v print(b % MOD) if __name__ == "__main__": main()
第二题
小红有a个1×1和b个2×2的正方形,她想知道能不能刚好用这a + b个拼成一个大正方形,使得这个正方形的每个位置都属于其中一块小正方形,且大正方形的每个位置不存在小正方形的重叠。
输入描述
第一行一个整数T(1 ≤ T ≤ 100),表示数据组数。
接下来T行,每行两个整数a, b(1 ≤ a, b ≤ 10^9),表示两种小正方形的个数。
输出描述
输出共T行,每行一个字符串,若能拼成大正方形输出"YES",否则输出"NO"。
样例输入
2
5 1
1 2
样例输出
YES
NO
参考题解
大正方形的面积必然是 A = a·1 + b·4。要拼出一个边长为 L 的正方形,必须有 L^2 = A。 先检查 A 是否为完全平方数 L^2; 再检查在这样边长的正方形内部,能否用恰好 b 个 2×2 方块填满所有“2×2”格子——也就是看 b == (L/2)^2(当且仅当 L 为偶数时才可能)。 两个条件同时满足则输出 “YES”,否则 “NO”。
C++:
#include <bits/stdc++.h> using namespace std; using ll = long long; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int T; cin >> T; while(T--){ ll a, b; cin >> a >> b; ll tot = a + 4LL * b; ll s = floor(sqrt((long double)tot)); while ((s+1)*(s+1) <= tot) s++; while (s*s > tot) s--; if (s*s != tot || b != (s/2)*(s/2)) { cout << "NO\n"; } else { cout << "YES\n"; } } return 0; }
Java:
// Java 版本 import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; import java.util.StringTokenizer; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); int T = Integer.parseInt(st.nextToken()); StringBuilder sb = new StringBuilder(); while (T-- > 0) { st = new StringTokenizer(br.readLine()); long a = Long.parseLong(st.nextToken()); long b = Long.parseLong(st.nextToken()); long tot = a + 4L * b; // 计算向下取整的平方根 long s = (l
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南