24秋招(2023.8.13)米哈游笔试真题解析

1.棋盘

题目内容

塔子哥有一个n*m的棋盘,一次移动可以选择上下左右四个方向移动一次,不同于普通棋盘,这个棋盘是循环的。

两个点可以一步到达,其中。同样的, 两个点也可以一步到达,其中

现在塔子哥需要从 A先走到 B 点,再从 B 点走到 C点,问最小移动次数是多少。

输入描述

第一行两个整数,

接下来三行,第一行是点 A 的坐标,第二行是点B 的坐标 ,第三行是点 C 的坐标

输出描述

输出从 A 到 B ,再从 B到 C 的最小移动次数

样例

输入

4 4
1 2
1 3
1 4

输出

2

题解:模拟

考虑任意点最小移动距离

首先,我们可以考虑从的移动距离

  • 方式1:直接到达:
  • 方式2:先走到,再由走到1,再由1走到

两种方式的移动取最小值,

因此最小移动距离

按照上述公式模拟即可

复杂度分析

时间复杂度:O(1)

空间复杂度:O(1)

C++

#include <bits/stdc++.h>
using namespace std;

typedef pair<int, int> PII;

int main()
{
    int n, m;
    cin >> n >> m;

    PII a, b, c;
    cin >> a.first >> a.second;
    cin >> b.first >> b.second;
    cin >> c.first >> c.second;

    long long ans = 0;
    // 从 a 到 b 的 x 轴
    ans += min(abs(a.first - b.first), n - abs(a.first - b.first));
    // 从 a 到 b 的 y 轴
    ans += min(abs(a.second - b.second), m - abs(a.second - b.second));
    // 从 b 到 c 的 x 轴
    ans += min(abs(b.first - c.first), n - abs(b.first - c.first));
    // 从 b 到 c 的 y 轴
    ans += min(abs(b.second - c.second), m - abs(b.second - c.second));

    cout << ans << "\n";
    return 0;
}

Java

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int m = scanner.nextInt();

        int[][] points = new int[3][2];
        for (int i = 0; i < 3; i++) {
            points[i][0] = scanner.nextInt();
            points[i][1] = scanner.nextInt();
        }

        long ans = 0;
        // 从 a 到 b 的 x 轴
        ans += Math.min(Math.abs(points[0][0] - points[1][0]), n - Math.abs(points[0][0] - points[1][0]));
        // 从 a 到 b 的 y 轴
        ans += Math.min(Math.abs(points[0][1] - points[1][1]), m - Math.abs(points[0][1] - points[1][1]));
        // 从 b 到 c 的 x 轴
        ans += Math.min(Math.abs(points[1][0] - points[2][0]), n - Math.abs(points[1][0] - points[2][0]));
        // 从 b 到 c 的 y 轴
        ans += Math.min(Math.abs(points[1][1] - points[2][1]), m - Math.abs(points[1][1] - points[2][1]));

        System.out.println(ans);
    }
}

Python

n, m = map(int, input().split())

points = []
for _ in range(3):
    x, y = map(int, input().split())
    points.append((x, y))

ans = 0
# 从 a 到 b 的 x 轴
ans += min(abs(points[0][0] - points[1][0]), n - abs(points[0][0] - points[1][0]))
# 从 a 到 b 的 y 轴
ans += min(abs(points[0][1] - points[1][1]), m - abs(points[0][1] - points[1][1]))
# 从 b 到 c 的 x 轴
ans += min(abs(points[1][0] - points[2][0]), n - abs(points[1][0] - points[2][0]))
# 从 b 到 c 的 y 轴
ans += min(abs(points[1][1] - points[2][1]), m - abs(points[1][1] - points[2][1]))

print(ans)

2.有根树的节点个数

题目内容

塔子哥有一个 n 个节点的树,树根编号为 1 。

塔子哥可以在叶子节点上添加一个新的儿子节点,添加后,添加的节点变成了新的叶子节点。

若干次操作后,塔子哥想问你距离树根不超过k 的节点最多可以有多少个。

输入描述

第一行,一个正整数n 表示树中节点个数,k 表示不超过树根的距离,

接下来 n-1行,每行输入两个整数 u和v ,表示节点u和v之间有一条边

输出描述

一个整数,表示若干次操作后距离树根不超过k的节点最大数量。

样例

输入

4 2
1 2
1 3
1 4

输出

7

样例解释

本身有4个节点到根节点的距离不超过k(1,2,3,4)
叶子节点是(2,3,4) 还可以再添加一个节点
因此总共的数量为4+3=7

题解:DFS+贡献法计数

考虑每一个节点对答案的贡献:如果当前节点距离根节点的距离d,则答案+1

此外,如果当前节点还是叶子节点,则说明还可以再叶子结点下添加个点,这些点可以构成一条链。

根据上述方式统计计数即可,注意本题题目给的是无向边,需要建两条有向边。

复杂度分析

时间复杂度:O(n)

空间复杂度:O(1)

C++

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n, k;
    cin >> n >> k;   
    // 建图
    vector<vector<int>> g(n);
    for (int i = 1; i < n; ++i) {
        int u, v;
        cin >> u >> v;
        u--; v--;
        g[u].emplace_back(v);
        g[v].emplace_back(u);
    }
    const int INF = 0x3f3f3f3f;
    long long ans = 0;
    vector<int> dist(n, INF);
    // 计算1号点到每个点的距离,1号点到自己的距离为 0
    dist[0] = 0;
    function<void(int,int)> dfs = [&](int u, int fa) {
        // 如果1号点到u+1点的距离 <= k,则答案加1
        if (dist[u] <= k) {
            ans += 1;
        }

        // 如果1号点到叶子的距离 < k,则还可以再这个叶子下加 k - dist[u] 个
        if (u != 0 && g[u].size() == 1 && dist[u] < k) {
            ans += k - dist[u];
        }

        // 继续遍历子树 v 
        for (int v: g[u]) {
            if (v == fa) continue;
            dist[v] = dist[u] + 1;
            dfs(v, u);
        }
    };
    
    dfs(0, -1);

    cout << ans << "\n";

    return 0;
}

Java

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main {
    static List<List<Integer>> g;
    static int[] dist;
    static int n, k;
    static long ans;

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        n = scanner.nextInt();
        k = scanner.nextInt();
        
        // 建图
        g = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            g.add(new ArrayList<>());
        }

        for (int i = 1; i < n; i++) {
            int u = scanner.nextInt() - 1;
            int v = scanner.nextInt() - 1;
            g.get(u).add(v);
            g.get(v).add(u);
        }

        final int INF = 0x3f3f3f3f;

        ans = 0;
        dist = new int[n];
        for (int i = 0; i < n; i++) {
            dist[i] = INF;
        }
        // 计算1号点到每个点的距离,1号点到自己的距离为 0
        dist[0] = 0;

        dfs(0, -1);

        System.out.println(ans);
    }

    static void dfs(int u, int fa) {
        // 如果1号点到u+1点的距离 <= k,则答案加1
        if (dist[u] <= k) {
            ans++;
        }
        // 如果1号点到叶子的距离 < k,则还可以再这个叶子下加 k - dist[u] 个
        if (u != 0 && g.get(u).size() == 1 && dist[u] < k) {
            ans += k - dist[u];
        }
        // 继续遍历子树 v 
        for (int v : g.get(u)) {
            if (v == fa) {
                continue;
            }
            dist[v] = dist[u] + 1;
            dfs(v, u);
        }
    }
}

Python3

def dfs(u, fa):
    global ans
    # 如果1号点到u+1点的距离 <= k,则答案加1
    if dist[u] <= k:
        ans += 1
    # 如果1号点到叶子的距离 < k,则还可以再这个叶子下加 k - dist[u] 个
    if u != 0 and len(g[u]) == 1 and dist[u] < k:
        ans += k - dist[u]
    # 继续遍历子树 v 
    for v in g[u]:
        if v == fa:
            continue
        dist[v] = dist[u] + 1
        dfs(v, u)


n, k = map(int, input().split())

# 建图
g = [[] for _ in range(n)]
for _ in range(1, n):
    u, v = map(int, input().split())
    u -= 1
    v -= 1
    g[u].append(v)
    g[v].append(u)

INF = int(1e9)

ans = 0
dist = [INF] * n
# 计算1号点到每个点的距离,1号点到自己的距离为 0
dist[0] = 0

dfs(0, -1)

print(ans)

3.原神抽卡

小米很喜欢在原神中抽卡,而且他只抽活动池。

活动池的抽卡有三种结果:非五星角色,五星限定角色,五星常驻角色。

抽到五星常驻角色和五星限定角色的概率均为,抽到非五星角色的概率为

如果抽到了五星常驻角色,则之后的抽卡结果将发生变化,变为的概率抽到五星限定角色,的概率抽到非五星卡。

如果连续89抽都没有抽到五星角色,则第90抽必定抽到一个五星限定角色或者五星常驻角色

给定一个概率,请你求出小米抽到五星限定角色的期望次数是多少?

输入格式

一个小数表示抽卡概率,

输出格式

一个小数,表示抽到五星限定角色的抽卡次数期望。你的答案和正确答案的误差不超过即视为正确

样例

输入

0.001

输出

129.1649522

题解:期望DP

我们可以发现,抽到第一次五星角色有50%的概率是限定五星角色,抽到第二次五星角色(如果第一次歪了)100%概率是限定五星角色,那么我们设第一次抽到五星角色为,第二次同理可得,也为,那么整体的抽到五星限定角色的概率就是

定义为第次抽到五星角色的概率,第次抽中,说明前次均没有抽中,因此状态转移方程为

期望就是概率乘权值

代码中可以使用前缀和优化,即可把变为

C++

#include <iostream>
using namespace std;
double dp[91];

int main() {
    double p;
    cin >> p;

    double cnt = 0; //记录总期望次数

    for (int i = 1; i < 90; i++) {
        dp[i] = (1 - dp[i - 1]) * p;
        cnt += dp[i] * i;
        dp[i] += dp[i - 1]; // 前缀和
    }

    cnt += 90 * (1 - dp[89]); // i = 90时特殊处理
    cout << fixed;
    cout.precision(7);
    cout << cnt * 1.5 << "\n";

    return 0;
}

Java

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        double p = sc.nextDouble();
        double[] dp = new double[91];
        double cnt = 0;		//记录总期望次数
        for(int i = 1 ; i < 90 ; i++) {
            dp[i] = (1-dp[i-1]) * p;
            cnt += dp[i] * i;
            dp[i] += dp[i-1];		//前缀和
        }
        cnt += 90 * (1-dp[89]);		//i=90时特殊处理
        System.out.printf("%.7f\n", cnt *1.5);
    }
}


Python

p = float(input())

dp = [0] * 91
cnt = 0 # 记录总期望次数

for i in range(1, 90):
    dp[i] = (1 - dp[i - 1]) * p
    cnt += dp[i] * i
    dp[i] += dp[i - 1]  # 前缀和

cnt += 90 * (1 - dp[89])  # i=90时特殊处理

print(f"{cnt * 1.5:.7f}")

以上内容均来自笔试刷题指南

#秋招##笔试##米哈游##笔试真题#
互联网笔试真题题解 文章被收录于专栏

收录近两年互联网公司笔试真题解析,并提供Java,Python,C++三种语言版本的代码

全部评论

相关推荐

不愿透露姓名的神秘牛友
07-11 11:21
被夸真的超级开心,好可爱的姐姐
码农索隆:老色批们不用脑补了,我把金智妮的图找来了查看图片
点赞 评论 收藏
分享
人力小鱼姐:实习经历没有什么含金量,咖啡店员迎宾这种就别写了,其他两段包装一下 想找人力相关的话,总结一下个人优势,结合校园经历里有相关性的部分,加一段自我评价
点赞 评论 收藏
分享
见见123:简历没有啥问题,是这个社会有问题。因为你刚毕业,没有工作经历,现在企业都不要没有工作经历的。社会病了。
点赞 评论 收藏
分享
评论
3
23
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务