牛客巅峰赛S2第三场题解(青铜白银组)

牛客巅峰赛S2第三场题解(青铜白银组)


更多内容欢迎关注我的公众号ACJavaBear,一起学习Java。


1.牛牛打怪

题目描述

牛牛在各个平台被各种传奇游戏的广告轰炸,所以他决定去玩一玩这类的游戏。这类游戏挂机就可以升级,所以牛牛每天都能变强。在第i天里,牛牛能杀死防御力小于等于i的怪物。但由于牛牛还要刷题,所以牛牛每天最多杀一只怪物。这个游戏共有n只怪物,每只怪物的防御力为DEF[i],牛牛想知道最少要到第几天才能把这n只怪物都杀死。

样例1

输入

2,[7,3]

返回

7

说明

牛牛可以在第3天杀死一只防御力为3的怪物,在第7天杀死一只防御力为7的怪物。所以牛牛最少能在第7天把这些怪物全杀死。
样例2

输入

3,[4,5,5]

返回

6

说明

牛牛可以在第4天杀死一只防御力为4的怪物,在第5天杀死一只防御力为5的怪物,在第六天将另一只防御力为5的怪杀死。所以牛牛最少能在第6天把这些怪物全杀死。
备注

1 ≤ n ≤ 1 0 3 , 1 ≤ D E F [ i ] ≤ 1 0 6 1≤n≤10^3, 1≤DEF[i]≤10^6 1n103,1DEF[i]106

题解

仔细读题可以发现,其实就是一个比较简单的动态规划问题

我们可以先把数组按升序排序,设一数组dpdp[i] 表示 把第 i i i 只怪兽打死需要到第几天。

而无非就两种情况,要么第 i i i 只怪兽的防御力大,所以应该到 DEF[i] 天才能打败它,要么就是我们现在就能打败第 i i i 只怪兽,但仍然需要花一天的时间,所以就是 dp[i-1] + 1 天。dp一维数组可以优化成一个变量存储 。

public class Solution {
    public int Minimumdays (int n, int[] DEF) {
        // write code here
        Arrays.sort(DEF);
        int cnt = DEF[0];
        for(int i = 1; i < n; i++){
            cnt = Math.max(DEF[i],cnt+1);
        }
        return cnt;
    }
}

2.简单的公式

题目描述

现在有3个数组a,b,c

a[1]=2,a[2]=6,对所有的n>=3,a[n] = 2a[n-1] + 3a[n-2]。

b[1]=7,b[2]=35,对所有的n>=3,b[n] = 3b[n-1] + 10b[n-2]。

对所有的n>=1,有c[n] = a[n]*b[n]。

现在给你一个正整数n,返回c[n]%1000000007的值。

样例1

输入

2

返回

210

说明

a[2]=6,b[2]=35,c[2]=a[2]*b[2]=210。
样例2

输入

10

返回

207027484
备注

对于百分之20的数据: 1 ≤ n ≤ 1 0 3 1≤n≤10^3 1n103

对于百分之50的数据: 1 ≤ n ≤ 1 0 7 1≤n≤10^7 1n107

对于百分之100的数据: 1 ≤ n ≤ 1 0 18 1≤n≤10^{18} 1n1018

请注意本题的空间限制为32MB

题解

根据两个递推公式,我们可以推出, a { n } a\{n\} a{n} b { n } b\{n\} b{n}两个等比数列

可以得出 a [ n ] = a 1 ∗ q n − 1 a[n] = a_1*q^{n-1} a[n]=a1qn1,即 a [ n ] = 2 ∗ 3 n − 1 a[n] = 2 * 3 ^{n-1} a[n]=23n1

同理可得 b [ n ] = 7 ∗ 5 n − 1 b[n] = 7 * 5 ^{n-1} b[n]=75n1

c [ n ] = 14 ∗ 1 5 n − 1 c[n] = 14 * 15 ^{n-1} c[n]=1415n1

到此由于数据范围最大可到 1 0 18 10^{18} 1018 ,所以我们需要用快速幂来求解。

import java.util.*;
public class Solution {
    long p = 1000000007;
    public int Answerforcn (long n) {
        // write code here
        return (int) (14 * qmi( 15,n-1) % p);
    }
    //快速幂模板
    public long qmi(long a,long b){
        long res = 1;
        while(b != 0){
            if((b & 1) == 1) res = res * a % p;
            b >>= 1;
            a = a * a % p;
        }
        return res; 
    }
}

3.Tree VI

题目描述

系统中有一棵n个点的完全k叉树,现给出它的DFS先序遍历序列 a i a_i ai,请你还原这棵树,并返回加密后的答案。 答案加密方法:所有边两个端点异或的和。

下面给出完全二叉树的定义:若设二叉树的深度为k,除第 k 层外,其它各层 (1~k-1) 的结点数都达到最大个数,第k层所有的结点都连续集中在最左边。 请你根据这个定义进行适度推广,得到完全k叉树的含义。

样例1

输入

2,[1,2,3,4,5]

返回

14

说明

树边为(1, 2), (1, 5), (2, 3), (2, 4),加密过程为(1^2)+(1^5)+(2^3)+(2^4),答案为14。
样例2

输入

3,[1,2,3,4,5]

返回

13

说明

树边为(1, 2), (1, 4), (1, 5), (2, 3),加密过程为(1^2)+(1^4)+(1^5)+(2^3),答案为13
备注

数据满足: 1 ≤ n , k ≤ 1 0 5 , 1 ≤ a i ≤ 1 0 9 1≤n,k≤10^5, 1≤ai≤10^9 1n,k105,1ai109

题解

由于数组给出的是 D F S DFS DFS 序,而之前我们做了一道 B F S BFS BFS 序的同类型题目。我们可以借助 B F S BFS BFS 序帮助遍历。具体见代码。

public class Solution {
    int kk = 0;
    int bfsOrder = 0; // 记录bfs序
    int dfsOrder = 0; // 记录dfs序,即为数组下标
    long res = 0;
    public long tree6 (int k, int[] a) {
        kk = k;
        dfs(a,bfsOrder);
        return res; 
    }
    
    public void dfs(int[] a,int bfsOrder){
        if(dfsOrder >= a.length) return ;
        int p = a[dfsOrder]; //记录当前结点值
        for(int i = 1; i <= kk; i++){
            if(bfsOrder * kk + i < a.length){ //判断当前结点有没有儿子
                dfsOrder++;                    //有儿子则到儿子一层
                res += (p ^ a[dfsOrder]);      //计算结果
                dfs(a,bfsOrder * kk + i);      //进入下一层
            }
        }
    }
}
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页