23年秋招-米哈游-笔试真题卷(1)

第一题:英语单词

在线测评链接:http://121.196.235.151/p/P1091

题目描述

ak机读小学了,学校里新开了英语课。

某一天老师进行了一对一的口语考试,考试内容为复述老师说的话。考试要求每个人一共进行 t t t次测试,每次测试中,老师会说一句话,包含 n n n个单词,ak机每复述出一个单词,就能够获得一分,但是当分数低于0时,本次测试就会结束,并且该次测试未通过。

ak机英语很差,因此他想知道自己一共能通过多少次测试。

输入描述

第一行输入一个正整数 t t t,代表ak机需要进行的测试数量

接下来的 3 × t 3\times t 3×t行,每3行用于描述一次测试:

第一行输入一个正整数 n n n,代表老师说的一句话包含的单词数量。

第二行输入 n n n个仅由小写字母组成的字符串,用空格隔开。代表老师说的单词。

第三行输入 n n n个仅由小写字母组成的字符串,用空格隔开。代表ak机复述的话。

1 ≤ t ≤ 10 , 1 ≤ n ≤ 100 1\le t \le 10,1\le n \le 100 1t10,1n100,单词的长度均不超过10。

输出描述

一个整数,代表ak机最终通过了多少次测试。

样例

输入

3
2
hello hello
hello hello
3
how are you
hwo are you
4
how old are you
how old are yuo

输出

2

题解:模拟

维护一个变量scorecnt表示ak机每次答题的分数和能通过多少次测试,如果某一轮测试中某一时刻的score的值<0,则直接跳出当前循环,如果最终有 s c o r e ≥ 0 score\ge 0 score0,则cnt计数+1。

C++

#include <bits/stdc++.h>
using namespace std;
const int N=2E5+10,mod=1e9+7;
int n,m;
string w[N],t[N];
int main(){
    cin>>n;
    int cnt=0;
    for(int i=0;i<n;i++){
        cin>>m;
        for(int i=0;i<m;i++){
            cin>>w[i];
        }
        for(int i=0;i<m;i++){
            cin>>t[i];
        }
        int score=0;
        for(int i=0;i<m;i++){
            if(w[i]==t[i])score++;
            else score--;
            if(score<0){
                break;
            }
        }
        if(score>=0){
            cnt++;
        }
    }
    cout<<cnt<<endl;
    return 0;
}

Java

import java.util.*;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int res = n;
        while (n -- > 0) {
            int len = sc.nextInt();
            sc.nextLine();
            String[] s1 = sc.nextLine().split(" ");
            String[] s2 = sc.nextLine().split(" ");
            int count = 0;
            for (int i = 0; i < len; i++) {
                if (s1[i].equals(s2[i])) {
                    count++;
                } else {
                    count--;
                }
                if (count < 0) {
                    res--;
                    break;
                }
            }
        }
        System.out.println(res);
    }
}

Python

t = eval(input())
final = 0
for _ in range(t):
    num = int(input())
    s1 = input().split()
    s2 = input().split()
    score = 0
    for j in range(num):
        if s1[j] == s2[j]:
            score +=1
        else:
            score -=1
        if score < 0:
            break
    if score >= 0:
        final += 1
print(final)

第二题:最小攻击次数

在线测评链接:http://121.196.235.151/p/P1092

题目描述

ak机最近沉迷于一款割草游戏。所谓割草游戏,并不是割草模拟器,而是指一款击杀敌人快,很容易一次性就击杀大量敌人的游戏。

ak机每放一个大范围aoe技能下去,就能看见屏幕上一大片的敌人消失,非常解压。

这天,ak机又在玩这款割草游戏了,他看着面前的 n n n个敌人,每个敌人都有 a i a_i ai的血,但是突然发现他的技能只能给一个敌人造成1点伤害了。但好在ak机所使用的角色点了天赋,开局时给所有敌人添加debuff,当一名敌人血量降到一半及以下时,就会给所有敌人造成1点伤害(这个debuff触发一次后消失)。ak机想知道,他最少需要多少次攻击才能击杀所有敌人。

输入描述

第一行输入一个正整数 n n n,代表敌人的最大数量

第二行输入 n n n个正整数 a i a_i ai,代表每个敌人的血量

1 ≤ n ≤ 1 0 5 , 1 ≤ a i ≤ 1 0 9 1\le n\le 10^5,1\le a_i \le 10^9 1n105,1ai109

输出描述

一个正整数,代表ak机攻击的最小次数。

样例

输入

2
6 8

输出

10

样例说明

先打第一个敌人3次,触发天赋,每个敌人剩余2,7血。接下来,打第二个敌人3次,触发天赋,每个敌人剩余1,3血。然后无法再触发天赋了,因此还要攻击4次,总共是10次。

题解:贪心+排序

为了尽可能减少攻击次数,我们肯定是想把天赋效果尽可能发挥满,也就是说,能被天赋aoe效果击败的怪物,我们就不主动攻击他

什么怪物必须要攻击呢,显然,天赋最多只能触发 n n n次,如果一个怪物的血量 ≥ n \ge n n,那么一定是要对他进行攻击的。

此外,对于血量更多的一些怪物,即使我们把它留到最后再去攻击(触发完其他所有怪物的aoe效果之后),它本身还是不会触发aoe效果,因此,我们需要将他们的aoe优先触发,这个血量阈值是 2 × n 2\times n 2×n

剩余的怪物,先触发血量少的怪物的aoe肯定会优于先触发血量多的情况,因为先触发血量多的可能会把血量少的打死,导致aoe伤害浪费,进而导致总攻击次数增多。

所以我们先将怪物按血量排序,然后计算血量大于 2 × n 2\times n 2×n的怪物的需要手动攻击的攻击次数,同时记录aoe的触发次数cnt,再依次从小到大依次处理

当我们判断第 i i i个敌人时,如果该敌人被天赋攻击cnt次后不能触发天赋,我们就要打到他触发天赋(血量少的要比血量多的先触发天赋,所以这里一定要打),如果可以触发就省去这一步,之后还要减去后面n-cnt个敌人天赋触发扣的血,敌人剩余的血量就是我们额外要攻击的次数,进行累加即可。

C++

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    int n;
    cin >> n;  // 输入怪物数量
    vector<int> w(n);
    for(int i = 0; i < n; i++) {
        cin >> w[i];  // 输入每个怪物的血量
    }
    sort(w.begin(), w.end());  // 对怪物血量进行排序
    int cnt = 0;  // 记录已经触发的aoe次数
    long long ans = 0;  // 记录总的攻击次数
    while (!w.empty() && w.back() >= 2 * n) { //先处理血量大于2*n的怪物
        ans += w.back() - n;  // 优先击杀它,并利用它的半血状态触发aoe
        w.pop_back();  // 移除已处理的怪物
        cnt++;  // aoe次数+1
    }
    for (int x : w) {  // 再依次从小到大处理剩余的怪物
        int hp_cur = x - cnt;  // 当前怪物接受完之前的aoe后的剩余血量
        if (hp_cur > x / 2) {  // 如果当前怪物没有触发aoe,就攻击他直到触发他的aoe
            ans += hp_cur - x / 2;
            hp_cur = x / 2;
        }
        if (hp_cur - (n - cnt) > 0) {  // 再计算当前怪物需要的攻击次数
            ans += hp_cur - (n - cnt);
        }
        cnt++;  // aoe次数+1
    }
    cout << ans << endl;  // 输出总的攻击次数
    return 0;
}

Java

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();  // 输入怪物数量
        List<Integer> w = new ArrayList<>();
        for(int i = 0; i < n; i++) {
            w.add(sc.nextInt());  // 输入每个怪物的血量
        }
        Collections.sort(w);  // 对怪物血量进行排序
        int cnt = 0;  // 记录已经触发的aoe次数
        long ans = 0;  // 记录总的攻击次数
        while (!w.isEmpty() && w.get(w.size() - 1) >= 2 * n) { //先处理血量大于2*n的怪物
            ans += w.get(w.size() - 1) - n;  // 优先击杀它,并利用它的半血状态触发aoe
            w.remove(w.size() - 1);  // 移除已处理的怪物
            cnt++;  // aoe次数+1
        }
        for (int x : w) {  // 再依次从小到大处理剩余的怪物
            int hp_cur = x - cnt;  // 当前怪物接受完之前的aoe后的剩余血量
            if (hp_cur > x / 2) {  // 如果当前怪物没有触发aoe,就攻击他直到触发他的aoe
                ans += hp_cur - x / 2;
                hp_cur = x / 2;
            }
            if (hp_cur - (n - cnt) > 0) {  // 再计算当前怪物需要的攻击次数
                ans += hp_cur - (n - cnt);
            }
            cnt++;  // aoe次数+1
        }
        System.out.println(ans);  // 输出总的攻击次数
    }
}

Python

n = int(input())
w = list(map(int, input().split()))
w.sort()
cnt = 0
ans = 0
while w and w[-1] >= 2*n:        #先处理血量大于2*n的怪物
    ans += w.pop() - n            #即便所有怪物死亡之后,也无法触发它的aoe,因此优先击杀它,并利用它的半血状态触发aoe量
    cnt += 1                    #记录已经触发的aoe次数
for x in w:        #再依次从小到大取数
    hp_cur = x - cnt            #当前怪物接受完之前的aoe后的剩余血量
    if hp_cur > x // 2:        #如果当前敌人没有触发aoe,就攻击他直到触发他的aoe
        ans += hp_cur - x//2
        hp_cur = x//2
    if hp_cur - (n-cnt) > 0:    #再计算当前敌人需要的攻击次数
        ans += hp_cur - (n-cnt)
    cnt += 1        #记录的aoe次数+1
print(ans)

第三题:魔法树

在线测评链接:http://121.196.235.151/p/P1062

题目描述

薯条哥是一名远近闻名的魔法师。

这天他受邀来到了一个国家,来帮这个国家的国王解决一个问题。这个国家的国王年轻时曾有一颗非常美丽的树,但是国王却不小心惹怒了一个十分邪恶的黑魔法师,于是黑魔法师施法,让这棵树变得十分丑陋。现在,这棵树一共有 n n n个节点,根节点为 1 1 1号节点,其深度为 1 1 1。每个节点都被黑魔法师随机施加了一个丑陋值,丑陋值越大,越影响这棵树的美观度,影响值为该节点的深度乘其丑陋值。

国王苦苦寻找了半辈子解决方案,让无数魔法师尝试过,但都没办法将树变回原样。长时间受黑魔法影响,这棵树再也无法变为原样了。终于,国王找到了薯条哥,希望薯条哥能尽可能地将树的影响值减少,并承诺,减少了多少影响值,就给薯条哥多少钱。

薯条哥看了看树,发现受黑魔法影响,只能裁剪树的一部分将其嫁接到另一个节点上。薯条哥想挣尽可能多的钱,因此他想知道能将树的影响值降到的最小值是多少?

注:只能裁剪一次。

输入描述

第一行输入一个整数 n ( 1 ≤ n ≤ 1 0 5 ) n(1 \leq n \leq 10^5) n(1n105)表示的大小

第二行输入 n n n个整数 a ( 1 ≤ a i ≤ 1 0 8 ) a(1 \leq a_i \leq 10^8) a(1ai108)表示每个节点的丑陋值

接下来 n − 1 n-1 n1行,每行输入两个整数 u , u ( 1 ≤ u , u ≤ n ) u,u(1 \leq u,u \leq n) u,u(1u,un),表示树上的边

输出描述

输出一个整数表示最小的影响值.

样例

输入

4
3 2 1 4
1 2
1 3
3 4

输出

17

说明

裁剪之前,如下图所示

裁剪之后,如下图所示

题解:树形DFS

根据题目描述我们可以发现,树的影响值受到两个因素影响:节点的丑陋值、节点离根节点的距离,因此,我们首先可以去利用上面一道题:有根树的节点数量的思路,来求出每一个节点到根节点的距离。

我们定义 d [ i ] d[i] d[i] i i i节点的深度, f [ i ] f[i] f[i]为以 i i i根节点的子树的影响值和,我们可以从根节点1开始,跑一遍DFS,来计算上述的值。

然后我们可以考虑裁剪第 i ( 2 ≤ i ≤ n ) i(2\le i \le n) i(2in)个节点,贪心的考虑,一定是把当前的节点,嫁接到根节点的位置上,那么,其实改变的影响值其实就是以 i i i为根节点的子树的影响值对应的部分。

我们需要去分析,第 i i i个节点裁剪前后的影响值的一个变化量。

  • 首先,如果第 i i i个节点是1号根节点的子节点,则就算裁剪,也不会对答案产生影响(距离根节点的距离无法再减少了)
  • 如果第 i i i个节点不是1号根节点的子节点,我们需要去分析裁剪前后的变化量,大家可以参考下面视频举得一个例子。

我们可以发现,对于第 i i i个节点裁剪后,对应的影响值变化量,是和节点 i i i到根节点的距离 d [ i ] d[i] d[i]以及以节点 i i i为根节点的子树的丑陋值之和有关。

因此,在一开始的dfs过程中,我们还需要预处理出每一个节点子树的丑陋值之和,记为 t o t a l [ i ] total[i] total[i]

i i i个节点裁剪前:距离根节点的距离为 d [ i ] d[i] d[i]

i i i个节点裁剪后:距离根节点的距离为2

因此,对应的变化量即为 ( d [ i ] − 2 ) × t o t a l [ i ] (d[i]-2)\times total[i] (d[i]2)×total[i]

因此对于第 i i i个节点,裁剪后对应的总的影响值即为 f [ 1 ] − ( d [ i ] − 2 ) × s u m [ i ] f[1]-(d[i]-2)\times sum[i] f[1](d[i]2)×sum[i]

我们枚举裁剪每一个节点对应的影响值,取最小值即为所求答案。

注意:本题数据范围较大,需要使用long long

C++

#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int>PII;
typedef long long ll;
const int N=2E5+10,mod=1e9+7;
int n,m;
ll f[N],w[N],d[N],total[N];
vector<int>g[N];
vector<ll> dfs(int u,int fa,int depth){  //预处理f[i],d[i],total[i]数组
    d[u]=depth;
    total[u]=w[u];
    f[u]+=1ll*w[u]*d[u];
    for(int &x:g[u]){
        if(x==fa)continue;
        auto t=dfs(x,u,depth+1);
        f[u]+=t[0];total[u]+=t[1];
    }
    return {f[u],total[u]};
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++)cin>>w[i];
    for(int i=1;i<n;i++){
        int a,b;
        cin>>a>>b;
        g[a].push_back(b);
        g[b].push_back(a);
    }
    dfs(1,0,1);
    ll res=f[1];
    for(int i=2;i<=n;i++){  //考虑替换第i个节点
        if(d[i]<=2)continue;
        ll down=1ll*(d[i]-2)*total[i];
        res=min(res,f[1]-down);
    }
    cout<<res<<endl;
    return 0;
}

Java

import java.util.*;

public class Main {
    static final int N = 200010;
    static final int mod = (int)1e9 + 7;
    static int n;
    static long[] f = new long[N], w = new long[N], d = new long[N], total = new long[N];
    static List<Integer>[] g = new ArrayList[N];

    static long[] dfs(int u, int fa, int depth) {
        d[u] = depth;
        total[u] = w[u];
        f[u] += 1L * w[u] * d[u];
        for (int x : g[u]) {
            if (x == fa) continue;
            long[] t = dfs(x, u, depth + 1);
            f[u] += t[0];
            total[u] += t[1];
        }
        return new long[]{f[u], total[u]};
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        for (int i = 1; i <= n; i++) {
            w[i] = sc.nextLong();
            g[i] = new ArrayList<>();
        }
        for (int i = 1; i < n; i++) {
            int a = sc.nextInt();
            int b = sc.nextInt();
            g[a].add(b);
            g[b].add(a);
        }
        dfs(1, 0, 1);
        long res = f[1];
        for (int i = 2; i <= n; i++) {
            if (d[i] <= 2) continue;
            long down = 1L * (d[i] - 2) * total[i];
            res = Math.min(res, f[1] - down);
        }
        System.out.println(res);
    }
}

Python

import sys
sys.setrecursionlimit(10**6)  # 设置递归深度上限
from collections import defaultdict

N = 200010
mod = int(1e9) + 7
n = 0
f = [0] * N
w = [0] * N
d = [0] * N
total = [0] * N
g = defaultdict(list)

def dfs(u, fa, depth):
    d[u] = depth
    total[u] = w[u]
    f[u] += 1 * w[u] * d[u]
    for x in g[u]:
        if x == fa:
            continue
        t = dfs(x, u, depth + 1)
        f[u] += t[0]
        total[u] += t[1]
    return f[u], total[u]

n = int(input())
w=[0]+list(map(int,input().split()))
for i in range(1, n):
    a, b = map(int, input().split())
    g[a].append(b)
    g[b].append(a)
dfs(1, 0, 1)
res = f[1]
for i in range(2, n + 1):
    if d[i] <= 2:
        continue
    down = 1 * (d[i] - 2) * total[i]
    res = min(res, f[1] - down)
print(res)
  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
米哈游Java后端笔试真题是面向Java后端开发岗位的一套笔试题目,旨在考察应聘者对Java后端开发的理解和应用能力。 这套笔试题目往往包含以下几个方面的内容: 1. Java语言基础:主要考察Java的基本语法、面向对象编程、常用类库等方面的知识。例如,常见的有关Java语言基础的题目有:反射机制的理解和应用、线程的创建和使用、异常处理等。 2. 数据库相关知识:主要考察应聘者对数据库的基本理解和SQL的使用能力。例如,常见的数据库相关题目有:数据库事务的概念和应用、数据库索引的优化策略、SQL语句的编写和调优等。 3. Web开发框架:主要考察应聘者对常用的Web开发框架的理解和应用能力。例如,常见的Web开发框架题目有:Spring框架的注解使用、MyBatis的配置和映射关系等。 4. 系统设计和优化:主要考察应聘者对大型系统设计和性能优化的能力。例如,常见的系统设计和优化题目有:数据库连接池的设计和实现、分布式系统的负载均衡策略、系统性能调优等。 总的来说,米哈游Java后端笔试真题是一套综合考察Java后端开发能力的题目,内容涵盖了Java语言基础、数据库相关知识、Web开发框架以及系统设计和优化等方面。应聘者需要具备扎实的Java编程基础,熟悉常用的开发框架和工具,以及对大型系统的设计和性能优化有一定的了解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值