米哈游笔试 米哈游笔试题 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%内容,订阅专栏后可继续查看/也可单篇购买
持续收录字节、腾讯、阿里、美团、美团、拼多多、华为等笔试题解,包含python、C++、Java多种语言版本,持续更新中。
查看12道真题和解析