恭喜发现宝藏!搜索公众号【TechGuide】回复公司名,解锁更多新鲜好文和互联网大厂的笔经面经。
作者@TechGuide【全网同名】
订阅专栏【进阶版】2023最新大厂笔试真题 & 题解,不容错过的宝藏资源!
第一题:最小登录天数
题目描述
dd最近迷上了玩阴阳师,现在眼前有一个永久勾玉卡,她在思考应不应该花费一定勾玉购买。
已知永久勾玉卡的价格是a勾玉,购买了永久勾玉卡之后每天登录游戏会返还6勾玉,但是三分钟热度的dd不知道自己能坚持玩几天,她想知道买了永久勾玉卡之后至少登录多少天她才可以回本。
输入描述
第一行一个正整数T(1<=T<=500),表示询问组数
接下来T行,每行两个正整数a,b,含义如上(1<=a,b<=10000000)
输出描述
T行,每行一个数,表示对应的答案。
样例
输入
3
10 1
10 2
10 3
输出
10
5
4
思路
签到题,直接看代码。
代码
Python版本
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int t = scanner.nextInt();
while (t-- > 0) {
int a = scanner.nextInt();
int b = scanner.nextInt();
System.out.println((a / b) + (a % b != 0));
}
}
}
# vx公众号关注TechGuide,代码可能需要少量调试。
Java版本
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int t = scanner.nextInt();
while (t-- > 0) {
int a = scanner.nextInt();
int b = scanner.nextInt();
System.out.println((a / b) + (a % b != 0));
}
}
}
// vx公众号关注TechGuide,代码可能需要少量调试。
第二题:整数切分
题目描述
小盖拿到了一个正整数。她准备把这个正整数切成若干个不大于 100 的数然后求和。小盖希望最终的和尽可能大,你能帮帮她吗?
输入描述
一个正整数x。
1<=x<=10^10000
输出描述
一个整数,代表切割后最大的和。
样例
输入
12345
输出
69
样例说明
切割成 1+23+45 即可。
思路
依然是动态规划,维护一个 dp数组,其中 dp[i] 表示从第1位到第i位的切割后的最大和。通过迭代计算 dp 数组,最终 dp[n] 即为切割后最大的和。
代码
Python版本
def solve():
x = input()
n = len(x)
dp = [0] * (n + 1)
for i in range(1, n + 1):
cur = 0
base = 1
for j in range(i, max(1, i - 2), -1):
cur += int(x[j - 1]) * base
base *= 10
if cur < 100:
dp[i] = max(dp[i], cur + dp[j - 1])
print(dp[n])
if __name__ == "__main__":
solve()
# vx公众号关注TechGuide,代码可能需要少量调试。
Java版本
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String x = scanner.next();
int n = x.length();
int[] dp = new int[n + 1];
for (int i = 1; i <= n; i++) {
int cur = 0;
int base = 1;
for (int j = i; j >= Math.max(1, i - 2); j--) {
cur += (x.charAt(j - 1) - '0') * base;
base *= 10;
if (cur < 100) {
dp[i] = Math.max(dp[i], cur + dp[j - 1]);
}
}
}
System.out.println(dp[n]);
}
}
// vx公众号关注TechGuide,代码可能需要少量调试。
第三题:语言交流
题目描述
小盖和朋友一共个人,一共有 m 种语言,每个人可能会多种语言,两个人可以交流当且仅当他们至少有一种共同的语言。小盖想知道,她和朋友们最少需要学多少种语言,任何人都可以和其他人进行交流。如果 A和B可以交流,B和C可以交流,那么A和C也可以间接的交流。
输入描述
第一行包含两个正整数n和,表示小盖的朋友的数量和语言的数量
接下来n行,每行第一个数ki,表示第i个人会ki种语言,接下来ki个数ai1,ai2…,aik,表示第i个人会的语言的编号。
1<=n<=1000
1<=m<=1000
1<=aij<=m
0<=ki<=m
输出描述
输出一个整数,表示小盖和朋友们最少需要学习的语言数量。
样例
输入
3 3
1 1
1 2
1 3
输出
2
样例说明
第二个人学习第一种语言,第三个人学习第二种语言,这样第一个人可以和第二个人交流,第二个人可以和第三个人交流。所有人都可以互相直接或间接交流。
思路
并查集,判断两个人是否有至少一种共同的语言,然后合并这两个人所在的集合,集合的数量就是小盖和朋友们最少需要学习的语言数量。
代码
Python版本
def father(i, f):
if f[i] == i:
return i
f[i] = father(f[i], f)
return f[i]
def connect(i, j, f):
fi = father(i, f)
fj = father(j, f)
if fi != fj:
f[fi] = fj
def solve():
n, m = map(int, input().split())
f = [i for i in range(n)]
first = [-1] * (m + 1)
for i in range(n):
cnt, *langs = map(int, input().split())
for lang in langs:
if first[lang] == -1:
first[lang] = i
else:
connect(i, first[lang], f)
has = any(first[i] != -1 for i in range(1, m + 1))
if not has:
print(n)
return
ans = sum(1 for i in range(n) if father(i, f) == i) - 1
print(ans)
if __name__ == "__main__":
solve()
# vx公众号关注TechGuide,代码可能需要少量调试。
Java版本
import java.util.Arrays;
import java.util.Scanner;
public class LanguageLearning {
public static void main(String[] args) {
solve();
}
static void solve() {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int m = scanner.nextInt();
int[] f = new int[n];
for (int i = 0; i < n; i++) {
f[i] = i;
}
int[] first = new int[m + 1];
Arrays.fill(first, -1);
for (int i = 0; i < n; i++) {
int cnt = scanner.nextInt();
for (int j = 0; j < cnt; j++) {
int lang = scanner.nextInt();
if (first[lang] == -1) {
first[lang] = i;
} else {
connect(i, first[lang], f);
}
}
}
boolean has = false;
for (int i = 1; i <= m; i++) {
if (first[i] != -1) {
has = true;
}
}
if (!has) {
System.out.println(n);
return;
}
int ans = 0;
for (int i = 0; i < n; i++) {
if (father(i, f) == i) {
ans++;
}
}
System.out.println(ans - 1);
}
static int father(int i, int[] f) {
if (f[i] == i) {
return i;
}
return f[i] = father(f[i], f);
}
static void connect(int i, int j, int[] f) {
int fi = father(i, f);
int fj = father(j, f);
if (fi != fj) {
f[fi] = fj;
}
}
}
// vx公众号关注TechGuide,代码可能需要少量调试。
第四题:路径均值
题目描述
小盖拿到了一棵树。她有多次查询,每次查询一条路上所有节点的平均数是多少。你帮帮她吗?
输入描述
第一行输入一个正整数n,代表树的节点数量。
第二行输入n个正整数ai,第i个正整数代表号节点的权值
接下来的n-1行,每行输入两个正整数u,v,代表节点u和节点u有一条边连接
接下来的一行输入一个正整数 q,代表查询次数。
接下来的9行,每行输入两个正整数x和y,代表一次查询,该次查询为节点x到节点Y路径上所有节点的平均数.
1<=n,q<=10^5
1<=ai<=10^9
输出描述
输出q行,每行输入一个整数,代表路径上的所有节点的平均数。
样例
输入
3
4 5 6
1 2
1 3
2
1 2
2 3
输出
500000008
5
思路
dfs,保存每个节点的权值和以及节点数量,计算两个节点的最近公共祖先和路径上所有节点的平均值。
代码
Python版本
def mod_pow(a, b, mod):
if b == 0:
return 1
res = mod_pow(a, b // 2, mod)
res = res * res % mod
if b % 2 == 1:
res = res * a % mod
return res
def dfs1(g, sum, cnt, a, cur, f):
if f != -1:
sum[cur] += sum[f]
cnt[cur] += cnt[f]
sum[cur] += a[cur]
cnt[cur] += 1
for next_node in g[cur]:
if next_node == f:
continue
dfs1(g, sum, cnt, a, next_node, cur)
def dfs2(g, fa, dep, root, fno):
fa[root][0] = fno
dep[root] = dep[fa[root][0]] + 1
for i in range(1, 31):
fa[root][i] = fa[fa[root][i - 1]][i - 1]
sz = len(g[root])
for i in range(sz):
if g[root][i] == fno:
continue
dfs2(g, fa, dep, g[root][i], root)
def lca(x, y, fa, dep):
if dep[x] > dep[y]:
x, y = y, x
tmp = dep[y] - dep[x]
j = 0
while tmp > 0:
if tmp & 1:
y = fa[y][j]
j += 1
tmp >>= 1
if y == x:
return y
for j in range(30, -1, -1):
if fa[x][j] != fa[y][j]:
x = fa[x][j]
y = fa[y][j]
return fa[y][0]
def solve():
n = int(input())
a = [0] + list(map(int, input().split()))
g = [[] for _ in range(n + 1)]
for _ in range(n - 1):
u, v = map(int, input().split())
g[u].append(v)
g[v].append(u)
sum_values = [0] * (n + 1)
cnt_values = [0] * (n + 1)
dfs1(g, sum_values, cnt_values, a, 1, 0)
fa_values = [[0] * 31 for _ in range(n + 1)]
dep_values = [0] * (n + 1)
dfs2(g, fa_values, dep_values, 1, 0)
q = int(input())
for _ in range(q):
u, v = map(int, input().split())
lc = lca(u, v, fa_values, dep_values)
tot = (sum_values[u] + sum_values[v] - 2 * sum_values[lc] + a[lc]) % MOD
c = cnt_values[u] + cnt_values[v] - 2 * cnt_values[lc] + 1
inv = mod_pow(c, MOD - 2, MOD)
ans = tot * inv % MOD
print(ans)
if name == "main":
solve()
# vx公众号关注TechGuide,代码可能需要少量调试。
Java版本
import java.util.*;
public class Main {
static final int MOD = 1000000007;
static long modPow(long a, long b) {
if (b == 0) return 1;
long res = modPow(a, b / 2);
res = res * res % MOD;
if (b % 2 == 1) {
res = res * a % MOD;
}
return res;
}
static void solve() {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[] a = new int[n + 1];
for (int i = 1; i <= n; i++) {
a[i] = scanner.nextInt();
}
List<List<Integer>> g = new ArrayList<>();
for (int i = 0; i <= n; i++) {
g.add(new ArrayList<>());
}
for (int i = 0; i < n - 1; i++) {
int u = scanner.nextInt();
int v = scanner.nextInt();
g.get(u).add(v);
g.get(v).add(u);
}
long[] sum = new long[n + 1];
int[] cnt = new int[n + 1];
dfs1(g, sum, cnt, a, 1, 0);
int[][] fa = new int[n + 1][31];
int[] dep = new int[n + 1];
dfs2(g, fa, dep, 1, 0);
int q = scanner.nextInt();
for (int i = 0; i < q; i++) {
int u = scanner.nextInt();
int v = scanner.nextInt();
int lc = lca(u, v, fa, dep);
long tot = sum[u] + sum[v] - 2 * sum[lc] + a[lc];
tot %= MOD;
long c = cnt[u] + cnt[v] - 2 * cnt[lc] + 1;
long inv = modPow(c, MOD - 2);
long ans = tot * inv % MOD;
System.out.println(ans);
}
}
static void dfs1(List<List<Integer>> g, long[] sum, int[] cnt, int[] a, int cur, int f) {
if (f != -1) {
sum[cur] += sum[f];
cnt[cur] += cnt[f];
}
sum[cur] += a[cur];
cnt[cur]++;
for (int next : g.get(cur)) {
if (next == f) continue;
dfs1(g, sum, cnt, a, next, cur);
}
}
static void dfs2(List<List<Integer>> g, int[][] fa, int[] dep, int root, int fno) {
fa[root][0] = fno;
dep[root] = dep[fa[root][0]] + 1;
for (int i = 1; i < 31; ++i) {
fa[root][i] = fa[fa[root][i - 1]][i - 1];
}
int sz = g.get(root).size();
for (int i = 0; i < sz; ++i) {
if (g.get(root).get(i) == fno) continue;
dfs2(g, fa, dep, g.get(root).get(i), root);
}
}
static int lca(int x, int y, int[][] fa, int[] dep) {
if (dep[x] > dep[y]) {
int temp = x;
x = y;
y = temp;
}
int tmp = dep[y] - dep[x];
for (int j = 0; tmp > 0; ++j, tmp >>= 1) {
if ((tmp & 1) == 1) y = fa[y][j];
}
if (y == x) return y;
for (int j = 30; j >= 0; --j) {
if (fa[x][j] != fa[y][j]) {
x = fa[x][j];
y = fa[y][j];
}
}
return fa[y][0];
}
public static void main(String[] args) {
solve();
}
}
// vx公众号关注TechGuide,代码可能需要少量调试。