第一题
组队竞赛
这道题目要注意的点是队伍的平均水平等于该队伍第二高水平,所以我们只需要让分出的几个队伍里第二高更大一点即可。
这道题我们只需要选择尽量打的两个数。可以借助排序来完成。
现在我们来观察取数的规律。来一个数据量更大的例子
一共有三组,第一组中间值下标为7,第二组下标为5,可以发现是依次减2的。有几组就循环几次。
加下来就可以根据逻辑写代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int num = 0;
int ret = 0;//记录返回值
cin >> num;
vector<int> score(3*num);
for (int i = 0; i < 3 * num; i++)
{
cin >> score[i];
}
sort(score.begin(), score.end());
for (int i = 0; i < num; i++)
{
ret += score[score.size() - 2 * (1 + i)];
}
cout << ret;
return 0;
}
提交后发现有报错,这是因为我们定义的ret为int类型的,然而数据太大超出了int能表示的范围。
我们需要将int改为long就可以,再提交一遍。
第二题,进制转换
如果n大于9,对应数字参考16进制。
借助十进制来描述
在十进制以内我们还是可以轻松解决的,但是后边字母表示如何来实现呢?
我们可以借助一个字符数组
那二进制举一个例子
模拟上边的过程即可求出答案
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
int m, n;
cin >> m >> n;
string s = "0123456789ABCDEF";
string ret;
while (m !=0)
{
ret=ret+s[m%n];
m /= n;
}
reverse(ret.begin(), ret.end());
cout << ret;
return 0;
}
运行后发现只会通过部分用例
这是因为我们忽略了0和负数的情况
所以我们要优化代码
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
int m, n;
int flag=0;
cin >> m >> n;
if(m==0)
{
cout<<0;
return 0;
}
else if(m<0)
{
m=0-m;
flag=1;
}
string s = "0123456789ABCDEF";
string ret;
while (m)
{
ret=ret+s[m%n];
m /= n;
}
if(flag==1)
{
ret+='-';
}
reverse(ret.begin(), ret.end());
cout<<ret;
return 0;
}
第三题
连续最大和
这道题要我们求出最大的连续子串的和,是因为数组中含有负数。
如何找到子数组的最大和呢?
我们可以来模拟一下
我们可以模拟上边的过程
在第一次时,max的值初始化为5,定义一个sum。sum一直向后遍历,当sum为负数且遇到一个正数时,就将sum变换为当前遍历的值。
已经分析的很清晰了,接下来是代码呈现。
#include <iostream>
#include <vector>
using namespace std;
int getMax(int a, int b){
return a>b? a:b;
}
int main(){
int num;
cin >> num;
vector<int> arr;
arr.resize(num);
for(int i=0; i<num; ++i){
cin >> arr[i];
}
int sum = arr[0];
int maxSum = arr[0];
for(int i=1; i<num; ++i){
sum = getMax(arr[i], sum+arr[i]);
if(sum > maxSum){
maxSum = sum;
}
}
cout << maxSum;
return 0;
}
这道题的状态方程式为
可以看出这里类似于一个动态规划的问题,dp[i]就是以i结尾的子数组的和。