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

news2025/6/9 17:07:06

🍭 大家好这里是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 += 1

print(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 -= x
        count += 1
    else:
        break

print(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;
    else
        t[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 = 0

def dfs(u, pre):
    global res
    t = [0, 0]
    if s[u - 1] == 'B':
        t[0] = 1
    else:
        t[1] = 1
    
    for 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 += 1
    
    return t

dfs(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;
        else
            t[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 defaultdict

MOD = 10 ** 9 + 7

def prime_factors(n):
    factors = {}
    i = 2
    while i * i <= n:
        while n % i == 0:
            factors[i] = factors.get(i, 0) + 1
            n //= i
        i += 1
    if n > 1:
        factors[n] = 1
    return factors

factors_dict = {i: prime_factors(i) for i in range(1, 11)}

def build_tree(node, start, end):
    if start == end:
        tree[node] = defaultdict(int)
        return
    mid = (start + end) // 2
    build_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:
        return
    if l <= start and end <= r:
        for fc, pow in factors_dict[val].items():
            tree[node][fc] += pow * (end - start + 1)
        return
    mid = (start + end) // 2
    update_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) // 2
    left = 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 factors

n, 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 += vi

q = int(input())
for _ in range(q):
    l, r = map(int, input().split())
    factors = query_tree(1, 1, n, l, r)
    ans = 1
    for pow in factors.values():
        ans = ans * (pow + 1) % MOD
    print(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领取,会在飞书进行同步的跟新。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1592460.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

sql server2008触发器

sql server在Navicat工具不能插入数据 可以去写代码插入&#xff0c;代码连接sql server可以插入 或者使用sql server专门的工具 BEGINdeclare a int;declare s t_amount;select a baddebt_age_id,srate from aa_baddebt_age;INSERT INTO dade(id,name) VALUES(a,s) END

Jackson 2.x 系列【16】反序列化器 JsonDeserializer

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Jackson 版本 2.17.0 源码地址&#xff1a;https://gitee.com/pearl-organization/study-jaskson-demo 文章目录 1. 概述2. 方法2.1 构造2.2 反序列化2.3 null 处理2.4 空值2.5 其他 3. 实现类3.…

基于SpringBoot+Vue的健身器材用品网站(源码+文档+部署+讲解)

一.系统概述 随着我国经济的高速发展与人们生活水平的日益提高&#xff0c;人们对生活质量的追求也多种多样。尤其在人们生活节奏不断加快的当下&#xff0c;人们更趋向于足不出户解决各种问题&#xff0c;必录德健身器材用品网展现了其蓬勃生命力和广阔的前景。与此同时&#…

Redis中的集群(九)

集群 消息 集群中的各个节点通过发送和接收消息(message)来进行通信&#xff0c;我们称发送消息的节点为发送者(sender),接收消息 的节点成为接收者&#xff0c;如图所示。节点发送的消息主要有以下五种: 1.MEET消息:当发送者接到客户端发送的CLUSTER MEET命令时&#xff0c…

# Nacos 服务发现-快速入门-创建服务消费者模块,使用 feign 调用 服务生产者

Nacos 服务发现-快速入门-创建服务消费者模块&#xff0c;使用 feign 调用 服务生产者 1、 新增 quickstart_consumer 子工程&#xff08;子模块&#xff09;&#xff0c; 创建子模块&#xff1a;--> 右键 nacos_discovery 父工程 --> Modules --> Maven --> G…

android gradle版本无法下载

android gradle版本无法下载问题解决方法 在引入一个新的android项目的时候&#xff0c;通常会因为无法下载gradle版本而一直卡在同步界面&#xff0c;类似于下面的情况。 这是因为gradle运行时首先会检查distributionUrlhttps://services.gradle.org/distributions/gradle-5.6…

·13·1dawwd

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话&#xff1a; 知不足而奋进&#xff0c;望远山而前行&am…

lv_micropython to download and building

想要在ESP32-C3使用Micropython开发GUI&#xff0c;所以需要编译lv_micropython&#xff0c;当前github上的版本是9.1.0。 一、开发环境 因为编译lv_micropython需要在linux系统下&#xff0c;但是我的电脑是windows系统&#xff0c;所以我在windows系统上安装了VMware虚拟机&…

牛客2024【牛客赛文X】春招冲刺ONT61 每日温度【hard 单调栈 Java、Go、PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/1f54e163e6944cc7b8759cc09e9c78d8 思路 单调栈最直接的应用就是获取数组中每个位置i,i的左边第一个比i大或者小的位置/数以及,i的右边第一个比i大或者小的位置/数不懂的同学看这里https://blog.csdn.net/Borsl…

Vulnhub靶机 DC-1渗透详细过程

Vulnhub靶机:DC-1渗透详细过程 目录 Vulnhub靶机:DC-1渗透详细过程一、将靶机导入到虚拟机当中二、攻击方式主机发现端口扫描web渗透利用msf反弹shell数据库信息web管理员密码提权 一、将靶机导入到虚拟机当中 靶机地址&#xff1a; https://www.vulnhub.com/entry/dc-1-1,29…

英伟达高性能芯片供货周期缩短到2-3个月,今年GPU不再紧缺?

戴尔台湾地区总经理Terence Liao近日称&#xff0c;英伟达高性能 AI GPU的交付周期在过去几个月中已从3-4个月缩短到仅2-3个月&#xff0c;进入2024年以来交货等待时间一直在不短缩短&#xff0c;目前的2-3个月已经是英伟达高性能GPU最短的交货期。 英伟达公司正在不断努力提高…

wsl下Linux使用chatglm.cpp记录

目录 前言 一些说明 过程 git chatglm.cpp代码 安装相关包 convert量化ggml cmake构建项目 命令行模型推理 webdemo模型推理 APIServer 性能表现 gpu推理设置 前言 Linux之前用的少&#xff0c;多数还是在Windows下操作&#xff0c;导致对Linux很陌生&#xff0c;…

MES系统中的业务过程管理流程

MES即制造执行系统&#xff0c;也可称为生产执行系统&#xff0c;是一套面向制造企业车间执行层的生产信息化管理系统。 mes系统的业务流程包括哪些方面呢&#xff1a; 一、生产计划与调度 mes系统中的生产计划与调度模块&#xff0c;能够根据企业生产实际情况&#xff0c;制…

淘宝批量采集商品详情数据(属性丨详情图丨sku丨价格等)

淘宝批量采集商品详情数据&#xff08;包括属性、详情图、SKU、价格等&#xff09;可以通过以下几种方式实现&#xff1a; 使用淘宝数据抓取工具&#xff1a;这类工具&#xff0c;如某鱼等&#xff0c;能够自动化采集淘宝商品数据&#xff0c;并将其转换成CSV、Excel等格式&am…

从0到1实现RPC | 12 限流

在服务提供者provider端添加限流逻辑 限流&#xff1a;指定时间内请求数超过指定阈值时就抛出异常。 在ProviderInvoker的调用过程中&#xff0c;添加限流逻辑&#xff1a; 使用滑动窗口SlidingTimeWindow统计30s的请求数&#xff1b;每个服务service对应一个滑动窗口&#…

pom.xml显示灰色并被划线

在使用 IDEA 进行开发的过程中&#xff0c;有时候会遇到 pom.xml 显示灰色并被划线的情况&#xff0c;如下图&#xff1a; 这一般是因为该文件被 Maven 忽略导致的&#xff0c;可以进行如下操作恢复&#xff1a; 设置保存后&#xff0c;可以看到 pom.xml 恢复了正常&#xff1a…

Go语言中如何正确使用 errgroup

不管是哪种编程语言,重新发明轮子都不是一个好主意。代码库重新实现如何启动多个goroutine并汇总错误也很常见。但是Go生态系统中的一个包旨在支持这种常见的用例。让我们来看看这个包并了解为什么它应该成为Go开发人员工具集的一部分。 golang.org/x是一个为标准库提供扩展的…

网络变压器(网络隔离变压器)是如何影响网通设备的传输速率的呢?

Hqst华轩盛(石门盈盛)电子导读&#xff1a;今天介绍网络变压器&#xff08;网络隔离变压器/网络滤波器&#xff09;是如何影响网通设备的传输速率的 一、网络变压器&#xff08;网络隔离变压器/网络滤波器&#xff09;的工作原理 网络变压器&#xff08;网络隔离变压器/网络滤…

04异常Lambda算法正则

异常 异常是什么&#xff1f; 异常是代码在编译或者执行的过程中可能出现的错误。避免异常的出现&#xff0c;同时处理可能出现的异常&#xff0c;让代码更稳健。 异常分为几类&#xff1f; 编译时异常、运行时异常。编译时异常&#xff1a;没有继承RuntimeExcpetion的异常…

python爬虫--------Beautiful Soup 案列(二十一天)

&#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; &#x1f388;&#x1f388;所属专栏&#xff1a;python爬虫学习&#x1f388;&#x1f388; ✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天…