【美团笔试题汇总】2024-04-13-美团春秋招笔试题-三语言题解(CPP/Python/Java)

2024-04-14 03:04

本文主要是介绍【美团笔试题汇总】2024-04-13-美团春秋招笔试题-三语言题解(CPP/Python/Java),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

🍭 大家好这里是KK爱Coding ,一枚热爱算法的程序员

✨ 本系列打算持续跟新美团近期的春秋招笔试题汇总~

💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导

👏 感谢大家的订阅➕ 和 喜欢💗

📧 KK这边最近正在收集近一年互联网各厂的笔试题汇总,如果有需要的小伙伴可以关注后私信一下 KK领取,会在飞书进行同步的跟新。

文章目录

    • 🍓 01.K小姐的好子矩阵
      • 问题描述
      • 输入格式
      • 输出格式
      • 样例输入
      • 样例输出
      • 数据范围
      • 题解
      • 参考代码
    • 🍇 02.卢小姐的魔法数组
      • 问题描述
      • 输入格式
      • 输出格式
      • 样例输入
      • 样例输出
      • 数据范围
      • 题解
      • 参考代码
    • 🥥 03.A先生的红黑树
      • 问题描述
      • 输入格式
      • 输出格式
      • 样例输入
      • 样例输出
      • 数据范围
      • 题解
      • 参考代码
    • 🧀 04.LYA的因子数量查询
      • 问题描述
      • 输入格式
      • 输出格式
      • 样例输入
      • 样例输出
      • 数据范围
      • 题解
      • 参考代码
    • 🍅 05.LYA的字符串子序列集合
      • 问题描述
      • 输入格式
      • 输出格式
      • 样例输入
      • 样例输出
      • 数据范围
      • 题解
      • 参考代码
    • 写在最后
    • 📧 KK这边最近正在收集近一年互联网各厂的笔试题汇总,如果有需要的小伙伴可以关注后私信一下 KK领取,会在飞书进行同步的跟新。

🍓 01.K小姐的好子矩阵

问题描述

K小姐拿到了一个 n n n m m m 列的矩阵,她想知道这个矩阵中有多少个 2 × 2 2 \times 2 2×2 的子矩阵是"好子矩阵"。一个子矩阵是"好子矩阵",当且仅当这个 2 × 2 2 \times 2 2×2 的子矩阵中的所有元素都相同。

输入格式

第一行包含两个正整数 n n n m m m,表示矩阵的行数和列数。

接下来的 n n n 行,每行包含 m m m 个正整数,表示这个矩阵。

输出格式

输出一个整数,表示 2 × 2 2 \times 2 2×2 好子矩阵的数量。

样例输入

3 3
1 2 1
1 1 1
1 1 3

样例输出

1

数据范围

1 ≤ n , m ≤ 100 1 \leq n, m \leq 100 1n,m100
1 ≤ a i , j ≤ 1 0 9 1 \leq a_{i,j} \leq 10^9 1ai,j109

题解

我们可以枚举矩阵中的每个 2 × 2 2 \times 2 2×2 的子矩阵,判断其是否为好子矩阵。具体做法如下:

  1. 枚举子矩阵的左上角位置 ( i , j ) (i, j) (i,j),其中 1 ≤ i ≤ n − 1 1 \leq i \leq n-1 1in1 1 ≤ j ≤ m − 1 1 \leq j \leq m-1 1jm1

  2. 对于每个 ( i , j ) (i, j) (i,j),判断以其为左上角的 2 × 2 2 \times 2 2×2 子矩阵是否为好子矩阵,即判断 a i , j a_{i,j} ai,j a i , j + 1 a_{i,j+1} ai,j+1 a i + 1 , j a_{i+1,j} ai+1,j a i + 1 , j + 1 a_{i+1,j+1} ai+1,j+1 是否都相等。

  3. 如果是好子矩阵,将答案加 1 1 1

  4. 枚举完所有的 ( i , j ) (i, j) (i,j) 后,即可得到好子矩阵的数量。

时间复杂度 O ( n m ) O(nm) O(nm),空间复杂度 O ( 1 ) O(1) O(1)

参考代码

  • Python
n, m = map(int, input().split())
matrix = [list(map(int, input().split())) for _ in range(n)]ans = 0
for i in range(n - 1):for j in range(m - 1):if matrix[i][j] == matrix[i][j + 1] == matrix[i + 1][j] == matrix[i + 1][j + 1]:ans += 1print(ans)
  • Java
import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();int m = sc.nextInt();int[][] matrix = new int[n][m];for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {matrix[i][j] = sc.nextInt();}}int ans = 0;for (int i = 0; i < n - 1; i++) {for (int j = 0; j < m - 1; j++) {if (matrix[i][j] == matrix[i][j + 1] && matrix[i][j] == matrix[i + 1][j] &&matrix[i][j] == matrix[i + 1][j + 1]) {ans++;}}}System.out.println(ans);}
}
  • Cpp
#include <iostream>
using namespace std;const int N = 110;
int matrix[N][N];int main() {int n, m;cin >> n >> m;for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {cin >> matrix[i][j];}}int ans = 0;for (int i = 0; i < n - 1; i++) {for (int j = 0; j < m - 1; j++) {if (matrix[i][j] == matrix[i][j + 1] && matrix[i][j] == matrix[i + 1][j] &&matrix[i][j] == matrix[i + 1][j + 1]) {ans++;}}}cout << ans << endl;return 0;
}

🍇 02.卢小姐的魔法数组

问题描述

卢小姐有一个长度为 n n n 的整数数组。她可以对数组进行最多 k k k 次操作,每次操作可以选择数组中的任意一个元素,将其加 1 1 1 或减 1 1 1。卢小姐希望经过这些操作后,数组中元素为 0 0 0 的数量尽可能多。你能帮助她计算出最多能有多少个元素变成 0 0 0 吗?

输入格式

第一行包含两个正整数 n n n k k k,分别表示数组的长度和最多的操作次数。

第二行包含 n n n 个整数 a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,,an,表示初始的数组。

输出格式

输出一个整数,表示经过最多 k k k 次操作后,数组中元素为 0 0 0 的最大数量。

样例输入

4 5
-2 3 -2 9

样例输出

2

数据范围

1 ≤ n ≤ 1 0 5 1 \leq n \leq 10^5 1n105
1 ≤ k ≤ 1 0 14 1 \leq k \leq 10^{14} 1k1014
− 1 0 9 ≤ a i ≤ 1 0 9 -10^9 \leq a_i \leq 10^9 109ai109

题解

可以先将数组中的元素全部转换为绝对值,然后对数组进行排序。接着从小到大遍历数组,对于每个元素,如果 k k k 减去当前元素的值大于等于 0 0 0,就将 k k k 减去当前元素的值,并将答案加 1 1 1。如果 k k k 的值已经小于当前元素,说明无法继续转换了,直接退出循环即可。

最终的答案即为数组中可以变成 0 0 0 的元素的最大数量。

时间复杂度为 O ( n log ⁡ n ) O(n \log n) O(nlogn),空间复杂度为 O ( n ) O(n) O(n)

参考代码

  • Python
n, k = map(int, input().split())
arr = list(map(int, input().split()))
arr = [abs(x) for x in arr]
arr.sort()count = 0
for x in arr:if k >= x:k -= xcount += 1else:breakprint(count)
  • Java
import java.util.Arrays;
import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();long k = sc.nextLong();long[] arr = new long[n];for (int i = 0; i < n; i++) {arr[i] = Math.abs(sc.nextLong());}Arrays.sort(arr);int count = 0;for (long x : arr) {if (k >= x) {k -= x;count++;} else {break;}}System.out.println(count);}
}
  • Cpp
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;const int N = 100010;
long long arr[N];int main() {int n;long long k;cin >> n >> k;for (int i = 0; i < n; i++) {cin >> arr[i];arr[i] = abs(arr[i]);}sort(arr, arr + n);int count = 0;for (int i = 0; i < n; i++) {if (k >= arr[i]) {k -= arr[i];count++;} else {break;}}cout << count << endl;return 0;
}

🥥 03.A先生的红黑树

问题描述

A先生有一棵 n n n 个节点的树,根节点编号为 1 1 1。树上的每个节点都被染成了红色或黑色。A先生想知道,有多少个节点满足以该节点为根的子树中同时包含红色节点和黑色节点。

输入格式

第一行包含一个正整数 n n n,表示树的节点数。

第二行包含一个长度为 n n n 的字符串 s s s,其中 s i s_i si 表示编号为 i i i 的节点的颜色。如果 s i s_i siB,则表示该节点为黑色;如果 s i s_i siR,则表示该节点为红色。

接下来 n − 1 n-1 n1 行,每行包含两个正整数 u u u v v v,表示节点 u u u 和节点 v v v 之间有一条边。

输出格式

输出一个整数,表示满足条件的节点个数。

样例输入

3
BRB
1 2
2 3

样例输出

2

数据范围

1 ≤ n ≤ 1 0 5 1 \leq n \leq 10^5 1n105

题解

可以使用深度优先搜索(DFS)来解决这个问题。对于每个节点,维护一个长度为 2 2 2 的数组 t t t,其中 t t t 表示以该节点为根的子树中是否包含黑色节点, t t t 表示以该节点为根的子树中是否包含红色节点。

在 DFS 过程中,首先根据当前节点的颜色更新 t t t 数组。然后递归地处理当前节点的每个子节点,并将子节点的 t t t 数组与当前节点的 t t t 数组进行按位或操作,更新当前节点的 t t t 数组。

最后,如果当前节点的 t t t 数组中 t t t t t t 都为 1 1 1,说明以该节点为根的子树中同时包含红色节点和黑色节点,将答案加 1 1 1

时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( n ) O(n) O(n)

参考代码

  • Cpp
#include <bits/stdc++.h>
using namespace std;vector<vector<int>> g;
string s;
int res = 0;vector<int> dfs(int u, int pre) {vector<int> t(2);if (s[u - 1] == 'B')t[0] = 1;elset[1] = 1;for (int v : g[u]) {if (v != pre) {vector<int> child = dfs(v, u);t[0] |= child[0];t[1] |= child[1];}}if (t[0] && t[1])res++;return t;
}int main() {int n;cin >> n;cin >> s;g.resize(n + 1);for (int i = 0; i < n - 1; i++) {int u, v;cin >> u >> v;g[u].push_back(v);g[v].push_back(u);}dfs(1, 0);cout << res << endl;return 0;
}
  • Python
n = int(input())
s = input()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)res = 0def dfs(u, pre):global rest = [0, 0]if s[u - 1] == 'B':t[0] = 1else:t[1] = 1for v in g[u]:if v != pre:child = dfs(v, u)t[0] |= child[0]t[1] |= child[1]if t[0] and t[1]:res += 1return tdfs(1, 0)print(res)
  • Java
import java.util.*;public class Main {static List<List<Integer>> g;static String s;static int res = 0;public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();s = sc.next();g = new ArrayList<>();for (int i = 0; i <= n; i++) {g.add(new ArrayList<>());}for (int i = 0; i < n - 1; i++) {int u = sc.nextInt();int v = sc.nextInt();g.get(u).add(v);g.get(v).add(u);}dfs(1, 0);System.out.println(res);}static int[] dfs(int u, int pre) {int[] t = new int[2];if (s.charAt(u - 1) == 'B')t[0] = 1;elset[1] = 1;for (int v : g.get(u)) {if (v != pre) {int[] child = dfs(v, u);t[0] |= child[0];t[1] |= child[1];}}if (t[0] == 1 && t[1] == 1)res++;return t;}
}

🧀 04.LYA的因子数量查询

问题描述

LYA有一个非常长的数组,数组中的元素都是正整数,且每个元素的取值范围为 1 1 1 10 10 10。为了方便描述,数组以连续段的形式给出,每个连续段用一个二元组 ( u i , v i ) (u_i, v_i) (ui,vi) 表示,其中 u i u_i ui 表示该段中的元素值, v i v_i vi 表示该段的长度。

现在,LYA需要进行 q q q 次查询,每次查询给定一个区间 [ l , r ] [l, r] [l,r],请你帮助她计算出该区间内所有元素的乘积的因子数量。由于答案可能很大,请对 1 0 9 + 7 10^9+7 109+7 取模后输出。

输入格式

第一行包含两个正整数 n n n m m m,分别表示数组的长度和连续段的数量。

接下来 m m m 行,每行包含两个正整数 u i u_i ui v i v_i vi,表示一个连续段。

m + 2 m+2 m+2 行包含一个正整数 q q q,表示查询的次数。

接下来 q q q 行,每行包含两个正整数 l l l r r r,表示一次查询的区间。

输出格式

输出共 q q q 行,每行输出一个整数,表示对应查询区间内所有元素的乘积的因子数量对 1 0 9 + 7 10^9+7 109+7 取模后的结果。

样例输入

6 3
1 2
2 1
3 3
2
1 3
2 6

样例输出

2
8

数据范围

1 ≤ n ≤ 1 0 14 1 \leq n \leq 10^{14} 1n1014
1 ≤ m , q ≤ 1 0 5 1 \leq m, q \leq 10^5 1m,q105
1 ≤ u i ≤ 10 1 \leq u_i \leq 10 1ui10
1 ≤ v i ≤ 1 0 9 1 \leq v_i \leq 10^9 1vi109
1 ≤ l ≤ r ≤ n 1 \leq l \leq r \leq n 1lrn
保证所有 v i v_i vi 之和等于 n n n

题解

本题可以使用线段树来解决。首先,我们可以预处理出每个数字 1 1 1 10 10 10 的质因子分解结果,存储在一个字典 factors_dict 中。然后,我们可以构建一棵线段树,树上的每个节点维护一个字典,表示该节点对应区间内每个质因子的次数。

对于每个连续段 ( u i , v i ) (u_i, v_i) (ui,vi),我们可以将其对应的质因子次数加到线段树的对应区间上。

对于每次查询 [ l , r ] [l, r] [l,r],我们可以通过线段树的区间查询,得到区间 [ l , r ] [l, r] [l,r] 内每个质因子的次数。然后,我们可以根据质因子次数计算出因子数量。设区间 [ l , r ] [l, r] [l,r] 内第 i i i 个质因子的次数为 c i c_i ci,则因子数量为 ∏ i ( c i + 1 ) \prod_{i} (c_i+1) i(ci+1)

最后,将因子数量对 1 0 9 + 7 10^9+7 109+7 取模后输出即可。

时间复杂度: O ( ( n + q ) log ⁡ n ) O((n+q) \log n) O((n+q)logn),其中 n n n 为数组长度, q q q 为查询次数。
空间复杂度: O ( n ) O(n) O(n)

参考代码

from collections import defaultdictMOD = 10 ** 9 + 7def prime_factors(n):factors = {}i = 2while i * i <= n:while n % i == 0:factors[i] = factors.get(i, 0) + 1n //= ii += 1if n > 1:factors[n] = 1return factorsfactors_dict = {i: prime_factors(i) for i in range(1, 11)}def build_tree(node, start, end):if start == end:tree[node] = defaultdict(int)returnmid = (start + end) // 2build_tree(node * 2, start, mid)build_tree(node * 2 + 1, mid + 1, end)tree[node] = defaultdict(int)def update_tree(node, start, end, l, r, val):if r < start or end < l:returnif l <= start and end <= r:for fc, pow in factors_dict[val].items():tree[node][fc] += pow * (end - start + 1)returnmid = (start + end) // 2update_tree(node * 2, start, mid, l, r, val)update_tree(node * 2 + 1, mid + 1, end, l, r, val)for fc in set(tree[node * 2]) | set(tree[node * 2 + 1]):tree[node][fc] = tree[node * 2][fc] + tree[node * 2 + 1][fc]def query_tree(node, start, end, l, r):if r < start or end < l:return defaultdict(int)if l <= start and end <= r:return tree[node]mid = (start + end) // 2left = query_tree(node * 2, start, mid, l, r)right = query_tree(node * 2 + 1, mid + 1, end, l, r)factors = defaultdict(int)for fc in set(left) | set(right):factors[fc] = left[fc] + right[fc]return factorsn, m = map(int, input().split())
tree = [None] * (4 * n)
build_tree(1, 1, n)index = 1
for _ in range(m):ui, vi = map(int, input().split())update_tree(1, 1, n, index, index + vi - 1, ui)index += viq = int(input())
for _ in range(q):l, r = map(int, input().split())factors = query_tree(1, 1, n, l, r)ans = 1for pow in factors.values():ans = ans * (pow + 1) % MODprint(ans)
  • Java
import java.io.*;
import java.util.*;public class Main {static final int MOD = (int) 1e9 + 7;static Map<Integer, Map<Integer, Integer>> factorsDict;static Map<Integer, Integer>[] tree;public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String[] line = br.readLine().split(" ");int n = Integer.parseInt(line[0]);int m = Integer.parseInt(line[1]);factorsDict = new HashMap<>();for (int i = 1; i <= 10; i++) {factorsDict.put(i, primeFactors(i));}tree = new Map[4 * n];buildTree(1, 1, n);int index = 1;for (int i = 0; i < m; i++) {line = br.readLine().split(" ");int ui = Integer.parseInt(line[0]);int vi = Integer.parseInt(line[1]);updateTree(1, 1, n, index, index + vi - 1, ui);index += vi;}int q = Integer.parseInt(br.readLine());for (int i = 0; i < q; i++) {line = br.readLine().split(" ");int l = Integer.parseInt(line[0]);int r = Integer.parseInt(line[1]);Map<Integer, Integer> factors = queryTree(1, 1, n, l, r);long ans = 1;for (int pow : factors.values()) {ans = ans * (pow + 1) % MOD;}System.out.println(ans);}}static Map<Integer, Integer> primeFactors(int n) {Map<Integer, Integer> factors = new HashMap<>();int i = 2;while (i * i <= n) {while (n % i == 0) {factors.put(i, factors.getOrDefault(i, 0) + 1);n /= i;}i++;}if (n > 1) {factors.put(n, 1);}return factors;}static void buildTree(int node, int start, int end) {if (start == end) {tree[node] = new HashMap<>();return;}int mid = (start + end) / 2;buildTree(node * 2, start, mid);buildTree(node * 2 + 1, mid + 1, end);tree[node] = new HashMap<>();}static void updateTree(int node, int start, int end, int l, int r, int val) {if (r < start || end < l) {return;}if (l <= start && end <= r) {for (Map.Entry<Integer, Integer> entry : factorsDict.get(val).entrySet()) {int fc = entry.getKey();int pow = entry.getValue();tree[node].put(fc, tree[node].getOrDefault(fc, 0) + pow * (end - start + 1));}return;}int mid = (start + end) / 2;updateTree(node * 2, start, mid, l, r, val);updateTree(node * 2 + 1, mid + 1, end, l, r, val);for (int fc : new HashSet<>(tree[node * 2].keySet())) {tree[node].put(fc, tree[node * 2].getOrDefault(fc, 0) + tree[node * 2 + 1].getOrDefault(fc, 0));}for (int fc : new HashSet<>(tree[node * 2 + 1].keySet())) {tree[node].put(fc, tree[node * 2].getOrDefault(fc, 0) + tree[node * 2 + 1].getOrDefault(fc, 0));}}static Map<Integer, Integer> queryTree(int node, int start, int end, int l, int r) {if (r < start || end < l) {return new HashMap<>();}if (l <= start && end <= r) {return tree[node];}int mid = (start + end) / 2;Map<Integer, Integer> left = queryTree(node * 2, start, mid, l, r);Map<Integer, Integer> right = queryTree(node * 2 + 1, mid + 1, end, l, r);Map<Integer, Integer> factors = new HashMap<>();for (int fc : new HashSet<>(left.keySet())) {factors.put(fc, left.getOrDefault(fc, 0) + right.getOrDefault(fc, 0));}for (int fc : new HashSet<>(right.keySet())) {factors.put(fc, left.getOrDefault(fc, 0) + right.getOrDefault(fc, 0));}return factors;}
}
  • Cpp
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;const int MOD = 1e9 + 7;
unordered_map<int, unordered_map<int, int>> factorsDict;
vector<unordered_map<int, int>> tree;unordered_map<int, int> primeFactors(int n) {unordered_map<int, int> factors;int i = 2;while (i * i <= n) {while (n % i == 0) {factors[i]++;n /= i;}i++;}if (n > 1) {factors[n] = 1;}return factors;
}void buildTree(int node, int start, int end) {if (start == end) {tree[node].clear();return;}int mid = (start + end) / 2;buildTree(node * 2, start, mid);buildTree(node * 2 + 1, mid + 1, end);tree[node].clear();
}void updateTree(int node, int start, int end, int l, int r, int val) {if (r < start || end < l) {return;}if (l <= start && end <= r) {for (auto entry : factorsDict[val]) {int fc = entry.first;int pow = entry.second;tree[node][fc] += pow * (end - start + 1);}return;}int mid = (start + end) / 2;updateTree(node * 2, start, mid, l, r, val);updateTree(node * 2 + 1, mid + 1, end, l, r, val);for (auto entry : tree[node * 2]) {int fc = entry.first;tree[node][fc] += entry.second;}for (auto entry : tree[node * 2 + 1]) {int fc = entry.first;tree[node][fc] += entry.second;}
}unordered_map<int, int> queryTree(int node, int start, int end, int l, int r) {if (r < start || end < l) {return {};}if (l <= start && end <= r) {return tree[node];}int mid = (start + end) / 2;auto left = queryTree(node * 2, start, mid, l, r);auto right = queryTree(node * 2 + 1, mid + 1, end, l, r);unordered_map<int, int> factors;for (auto entry : left) {int fc = entry.first;factors[fc] += entry.second;}for (auto entry : right) {int fc = entry.first;factors[fc] += entry.second;}return factors;
}int main() {ios::sync_with_stdio(false);cin.tie(nullptr);for (int i = 1; i <= 10; i++) {factorsDict[i] = primeFactors(i);}int n, m;cin >> n >> m;tree.resize(4 * n);buildTree(1, 1, n);int index = 1;for (int i = 0; i < m; i++) {int ui, vi;cin >> ui >> vi;updateTree(1, 1, n, index, index + vi - 1, ui);index += vi;}int q;cin >> q;while (q--) {int l, r;cin >> l >> r;auto factors = queryTree(1, 1, n, l, r);long long ans = 1;for (auto entry : factors) {int pow = entry.second;ans = ans * (pow + 1) % MOD;}cout << ans << '\n';}return 0;
}

🍅 05.LYA的字符串子序列集合

问题描述

LYA有一个由数字组成的字符串 s s s。她从 s s s 中选出了所有的非空子序列,并将其中满足相邻字符不相同的子序列都加入到了集合 S S S 中。现在她想知道,集合 S S S 中有多少个不同的子序列。注意,允许子序列以 0 0 0 开头,并且以 0 0 0 开头的子序列和不以 0 0 0 开头的子序列是不同的。

输入格式

输入包含一行,为一个由数字组成的字符串 s s s,表示LYA的字符串。字符串 s s s 的长度不超过 1 0 6 10^6 106,可能包含前导 0 0 0

输出格式

输出包含一行,为一个整数,表示集合 S S S 中不同子序列的数量。答案可能很大,请对 1 0 9 + 7 10^9+7 109+7 取模后输出。

样例输入

12121

样例输出

9

数据范围

0 ≤ s ≤ 1 0 1000000 0 \leq s \leq 10^{1000000} 0s101000000

题解

这道题可以使用动态规划来解决。设 d p [ i ] [ j ] dp[i][j] dp[i][j] 表示考虑前 i i i 个字符,最后一个字符为 j j j 的满足条件的子序列的数量。初始化 d p [ i n t ( x ) ] = 1 dp[int(x)] = 1 dp[int(x)]=1,表示只考虑第一个字符时,以该字符结尾的子序列数量为 1 1 1。对于第 i i i 个字符 c c c,需要更新 d p [ i ] [ j ] dp[i][j] dp[i][j]:

  • 如果 j ≠ c j \neq c j=c,则 d p [ i ] [ j ] = d p [ i − 1 ] [ j ] dp[i][j] = dp[i-1][j] dp[i][j]=dp[i1][j],因为以 j j j 结尾的子序列数量不变。
  • 如果 j = c j = c j=c,则 d p [ i ] [ c ] = ∑ k = 0 9 d p [ i − 1 ] [ k ] − d p [ i − 1 ] [ c ] + 1 dp[i][c] = \sum_{k=0}^9 dp[i-1][k] - dp[i-1][c] + 1 dp[i][c]=k=09dp[i1][k]dp[i1][c]+1,因为以 c c c 结尾的子序列数量等于前 i − 1 i-1 i1 个字符的所有子序列数量,再减去前 i − 1 i-1 i1 个字符中以 c c c 结尾的子序列数量,最后加上空序列。

最终答案为 ∑ j = 0 9 d p [ n ] [ j ] \sum_{j=0}^9 dp[n][j] j=09dp[n][j],即考虑所有字符后,以任意字符结尾的满足条件的子序列数量之和。时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( n ) O(n) O(n)

参考代码

  • Python
#include <iostream>
using namespace std;const int MOD = 1e9 + 7;int main() {string s;cin >> s;int n = s.length();long long dp[n + 1][10];for (int i = 0; i <= n; i++) {for (int j = 0; j < 10; j++) {dp[i][j] = 0;}}dp[1][s[0] - '0'] = 1;for (int i = 2; i <= n; i++) {for (int j = 0; j < 10; j++) {if (j != s[i - 1] - '0') {dp[i][j] = dp[i - 1][j];}}long long sum = 0;for (int j = 0; j < 10; j++) {sum = (sum + dp[i - 1][j]) % MOD;}dp[i][s[i - 1] - '0'] = (sum - dp[i - 1][s[i - 1] - '0'] + 1 + MOD) % MOD;}long long ans = 0;for (int j = 0; j < 10; j++) {ans = (ans + dp[n][j]) % MOD;}cout << ans << endl;return 0;
}
  • Java
import java.util.Scanner;public class Main {static final int MOD = (int) 1e9 + 7;public static void main(String[] args) {Scanner sc = new Scanner(System.in);String s = sc.next();int n = s.length();long[][] dp = new long[n + 1][10];dp[1][s.charAt(0) - '0'] = 1;for (int i = 2; i <= n; i++) {for (int j = 0; j < 10; j++) {if (j != s.charAt(i - 1) - '0') {dp[i][j] = dp[i - 1][j];}}long sum = 0;for (int j = 0; j < 10; j++) {sum = (sum + dp[i - 1][j]) % MOD;}dp[i][s.charAt(i - 1) - '0'] = (sum - dp[i - 1][s.charAt(i - 1) - '0'] + 1 + MOD) % MOD;}long ans = 0;for (int j = 0; j < 10; j++) {ans = (ans + dp[n][j]) % MOD;}System.out.println(ans);}
}
  • Cpp
#include <iostream>
using namespace std;const int MOD = 1e9 + 7;int main() {string s;cin >> s;int n = s.length();long long dp[n + 1];dp[0] = 1;int last[10];for (int i = 0; i < 10; i++) {last[i] = -1;}for (int i = 1; i <= n; i++) {int digit = s[i - 1] - '0';if (i == 1 || s[i - 1] != s[i - 2]) {dp[i] = dp[i - 1] * 2 % MOD;} else {dp[i] = dp[last[digit] + 1] * 2 % MOD;}if (last[digit] != -1) {dp[i] -= dp[last[digit]];}dp[i] = (dp[i] + MOD) % MOD;last[digit] = i;}cout << (dp[n] - 1 + MOD) % MOD << endl;return 0;
}

写在最后

📧 KK这边最近正在收集近一年互联网各厂的笔试题汇总,如果有需要的小伙伴可以关注后私信一下 KK领取,会在飞书进行同步的跟新。

在这里插入图片描述

这篇关于【美团笔试题汇总】2024-04-13-美团春秋招笔试题-三语言题解(CPP/Python/Java)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/901914

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

2024年流动式起重机司机证模拟考试题库及流动式起重机司机理论考试试题

题库来源:安全生产模拟考试一点通公众号小程序 2024年流动式起重机司机证模拟考试题库及流动式起重机司机理论考试试题是由安全生产模拟考试一点通提供,流动式起重机司机证模拟考试题库是根据流动式起重机司机最新版教材,流动式起重机司机大纲整理而成(含2024年流动式起重机司机证模拟考试题库及流动式起重机司机理论考试试题参考答案和部分工种参考解析),掌握本资料和学校方法,考试容易。流动式起重机司机考试技