2018年清华大学软件学院夏令营机试题解

原题博客:

https://blog.csdn.net/wangkingkingking/article/details/80666385

第二题我觉得他的做法会TLE。

5e9肯定只能n啊

但是我这个人代码老是写错,所以希望大家指正一下。

前提:a一定要小于5e9。我觉得作为一道正常的题目,a到1e7就够了吧,硬要卡MLE就是狗了

思路:

我的想法是,因为凸函数的任何极小值也是最小值。严格凸函数最多有一个最小值。所以我们可以从差分(相当于求导)的思路来做,首先讲f(i)作差分,存进一个数组,然后每行输入一个a,b。动动脑子就知道b肯定是没有用的,所以相当于所有的差分数组加a求最接近0的值就是f(i)的最值。但是如果根据差分的递减性质进行二分查找,这就是一个没有灵魂的算法,因为复杂度还是log没有根本的变化。

因此其实差分后我们还要做一个预处理,将差分数组进行四舍五入,然后存入一个新的数组。这里就是我觉得题目应该不太对的地方,因为a应该会有一个取值范围的,这样我们记录a取值范围内的四舍五入结果到一个数组里面。(这里会有负数,所以可能要做一个简单的数组变化,就是将1e7当作0)然后对差分数组进行遍历四舍五入,如果在-1e7-1e7之内,就将差分的下标存在具体数据里面。

然后再考虑一下重复的情况。重复的情况就是假设有一块四舍五入全部都是一个数。找最接近的那一个。考虑到上凸函数的性质,只要找到最接近整数的那一个数就行了。因此,再设置一个double 型数组存未四舍五入的值。如果下表数组为-1(初始化,表示没有存过),则直接存储double型和int型。否则,比较double的结果,如果更加接近,替换。否则,过掉。

这样的好处是,只要获得了一个a,就已经知道了位置(int型数组的-a)。直接输出哪个位置的新函数结果即可。注意考虑最顶端的两个到底谁大谁小,因此比较一下即可。


代码:

#include
#include
#include
#include
using namespace std;
int n,m;
double f[5000000005];
double cha[5000000005];
double zhi[5000000005*2];
int shu[5000000005*2];
int bian(int a)
{
	return a+5000000000;
}
int main()
{
	while (~scanf("%d%d",&n,&m))
	{
		for (int i=0;i5000000000*2) continue;//超出范围直接取消,因为没用 
			if (shu[xiabiao]==-1)
			{
				shu[xiabiao]=i;
				zhi[xiabiao]=cha[i];
				continue;
			}
			if (shu[xiabiao]!=-1)
			{
				if (fabs(cha[i]-i)

 

你可能感兴趣的:(算法训练)