米哈游笔试 米哈游笔试题 0817

笔试时间:2024年08月17日 秋招

历史笔试传送门:2023秋招笔试合集

第一题

题目:米小游的原石计划

为了抽到心爱的五星角色,米小游需要至少 n 颗原石。 目前米小游手里没有任何的原石,距离卡池结束还有 m 天。 原石有两种获取方式,一种是充小月卡,另一种是直接买。 1.充一次月卡需要 30 块钱,可以增加 30 天的祝福次数,每天只能领一次祝福(90原石),购买当天可额外领取 300原石。 2.直接买则是 1 块钱 10 原石。 为了尽可能省钱,他希望你帮他求出最少的花费。

输入描述

第一行有两个整数 n(1<=n<=2.10^5) 和m(1<=m<=240) 。

输出描述

输出一个整数,代表最少的花费 。

样例输入

3200 35

样例输出

50

说明

充一次小月卡,然后额外充20块钱。

参考题解

由于月卡可以一次性获得300,那我们可以得出以下结论:除非我们仍然需要的数量不足300,否则一定是买月卡划算。接下来按照n的余量进行循环即可。

C++:[此代码未进行大量数据的测试,仅供参考]

#include <iostream>

int main() {
    int n, m;
    std::cin >> n >> m;
    int cnt = 0;

    while (n > 0) {
        if (n >= 300) {
            // 月卡
            cnt += 30;
            if (m >= 30) {
                m -= 30;
                n -= 300 + 90 * 30;
            } else {
                n -= 300 + 90 * m;
                m = 0;
                cnt += n / 10;
                n = 0;
            }
        } else {
            cnt += n / 10;
            n = 0;
        }
    }

    std::cout << cnt << std::endl;
    return 0;
}

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 cnt = 0;

        while (n > 0) {
            if (n >= 300) {
                // 月卡
                cnt += 30;
                if (m >= 30) {
                    m -= 30;
                    n -= 300 + 90 * 30;
                } else {
                    n -= 300 + 90 * m;
                    m = 0;
                    cnt += n / 10;
                    n = 0;
                }
            } else {
                cnt += n / 10;
                n = 0;
            }
        }

        System.out.println(cnt);
    }
}

Python:[此代码未进行大量数据的测试,仅供参考]

n,m = map(int, input().split())
cnt = 0
while n > 0:
    if n>= 300:
        #月卡
        cnt += 30
        if m >= 30:
            m-=30
            n -= 300 + 90 * 30
        else:
            n -= 300 + 90 * m
            m = 0
            cnt += n//10
            n = 0
    else:
        cnt += n//10
        n = 0

print(cnt)

第二题

题目:米小游种树(一)

一条长度为 n 的公路上,米小游雇佣了 m 名植树工,其中第 i 位工人会给 [li,ri] 这一段区间中的每个点都种上一棵树。图片但由于每个点最多种一棵树,因此如果某位工人发现自己要种的地方已经有树,自己就会跳过这个点不管。图片米小游为了节约成本,现在要恰好少雇佣一名工人,但同时他不希望少了此人会影响最终种树的结果,现在请你帮他算算有多少名工人都可以成为恰好少雇佣的这一名呢。

输入描述

第一行输入两个正整数 n,m (1<=n<=2*10^5;1<=m<=10^5 ) 代表公路长度和植树工人数量。

接下来 m 行,每行输入两个正整数 li,ri (1<=li<=ri<=n) 代表第 i 位工人负责种树的区域。

输出描述

在一行上输出一个整数,代表有多少名工人可以被解雇。

样例输入一

5 3

1 4

1 2

3 4

样例输出一

3

说明

三名工人都可以成为被解雇的那一个。

最终的种树结果为: [1,1,1,1,0](1 表示有树,0 表示没有。)

解雇第一位工人,种树结果依然为 [1,1,1,1,0]:不会影响结果。

解雇第二位工人,依然不会影响结果。

解雇第三位工人,依然不会影响结果。

样例输入二

4 2

1 2

3 4

样例输出二

0

说明

每名工人都不可或缺。

最终种树结果为:[1,1,1,1]。

如果解雇第一位工人,则结果变为:[0,0,1,1],影响了结果。

如果解雇第二位工人,则结果变为:[1,1,0,0],影响了结果。

参考题解

首先使用差分数组处理出所有的工人操作后的结果。那么对于某一个工人(区间)来讲,如何判断是否可以裁员呢?那么就是他负责的这个区间内的最小值大于1,那么说明他走了以后区间的所有位置仍然有其他工人顶上的,那么这里就可以使用ST表来快速查询。

C++:[此代码未进行大量数据的测试,仅供参考]

#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>

using namespace std;

vector<vector<int>> f;
vector<int> Logn;

void precompute(const vector<int>& arr) {
    int n = arr.size();
    int logn = floor(log2(n)) + 1;

    f.assign(n, vector<int>(logn));
    Logn.assign(n + 1, 0);

    // Calculate Log values
    for (int i = 2; i <= n; i++) {
        Logn[i] = Logn[i / 2] + 1;
    }

    // Initialize the first column of the sparse table
    for (int i = 0; i < n; i++) {
        f[i][0] = arr[i];
    }

    // Fill the sparse table
    int j = 1;
    while ((1 << j) <= n) {
        int i = 0;
        while (i + (1 << j) - 1 < n) {
            f[i][j] = min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
            i++;
        }
        j++;
    }
}

int query(int L, int R) {
    int s = Logn[R - L + 1];
    return min(f[L][s], f[R - (1 << s) + 1][s]);
}

int main() {
    int n, m;
    cin >> n >> m;
    vector<int> diff(n);

    vector<pair<int, int>> itvs(m);
    for (int i = 0; i < m; i++) {
        int l, r;
        cin >> l >> r;
        l--; r--;
        itvs[i] = {l, r};
        diff[l]++;
        if (r + 1 < n) diff[r + 1]--;
    }

    vector<int> res(n);
    res[0] = diff[0];
    for (int i = 1; i < n; i++) {
        res[i] = res[i - 1] + diff[i];
    }
    precompute(res);

    int cnt = 0;
    for (const auto& itv : itvs) {
        if (query(itv.first, itv.second) > 1) {
            cnt++;
        }
    }

    cout << cnt << endl;
    return 0;
}

Java:[此代码未进行大量数据的测试,仅供参考]

import java.util.Scanner;

public class Main {
    privat

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

2024 BAT笔试合集 文章被收录于专栏

持续收录字节、腾讯、阿里、美团、美团、拼多多、华为等笔试题解,包含python、C++、Java多种语言版本,持续更新中。

全部评论
在文本框内写代码吗,可以使用本地ide吗
点赞 回复 分享
发布于 09-03 14:24 江西

相关推荐

小红书 后端选手 n*16*1.18+签字费期权
点赞 评论 收藏
分享
Java抽象带篮子:难蚌,点进图片上面就是我的大头😆
点赞 评论 收藏
分享
头像
11-27 14:28
长沙理工大学
刷算法真的是提升代码能力最快的方法吗?&nbsp;刷算法真的是提升代码能力最快的方法吗?
牛牛不会牛泪:看你想提升什么,代码能力太宽泛了,是想提升算法能力还是工程能力? 工程能力做项目找实习,算法也分数据结构算法题和深度学习之类算法
点赞 评论 收藏
分享
评论
1
16
分享
牛客网
牛客企业服务