牛客巅峰赛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天把这些怪物全杀死。
备注
题解
仔细读题可以发现,其实就是一个比较简单的动态规划问题。
我们可以先把数组按升序排序,设一数组dp
,dp[i]
表示 把第 只怪兽打死需要到第几天。
而无非就两种情况,要么第 只怪兽的防御力大,所以应该到 DEF[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的数据:
对于百分之50的数据:
对于百分之100的数据:
请注意本题的空间限制为32MB
题解
根据两个递推公式,我们可以推出, 与 为两个等比数列。
可以得出 ,即
同理可得
故 。
到此由于数据范围最大可到 ,所以我们需要用快速幂来求解。
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先序遍历序列 ,请你还原这棵树,并返回加密后的答案。 答案加密方法:所有边两个端点异或的和。
下面给出完全二叉树的定义:若设二叉树的深度为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
备注
数据满足:
题解
由于数组给出的是 序,而之前我们做了一道 序的同类型题目。我们可以借助 序帮助遍历。具体见代码。
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); //进入下一层
}
}
}
}