【NOI2000T1】瓷片项链-二次函数的最值
测试地址:瓷片项链
注意,该测试地址中的式子写错了,应该是D=0.3*(V-V0)^0.5(也就是D=0.3*sqrt(V-V0)),漏了一个^0.5,看得我不明所以...找到了原题才知道少了个根号。
做法:设分成s块,要求总长W=sD最大,化一下式子:
W=sD=s*0.3*sqrt(V总/s-V0)=0.3*sqrt(V总s-V0s^2)
注意到根号内的式子(V总s-V0s^2)是一个关于s的二次函数,这个式子越大,W就越大,所以问题转化为求二次函数(V总s-V0s^2)取最大值时s的取值,由于二次项系数小于0,所以函数在顶点处取最大值,由初中的数学知识得bests=V总/(2*V0)。然而,bests可能不是整数,而问题要求整数解,由二次函数的图象可知,离顶点横坐标越接近的点的函数值越大,所以我们就比较bests与其向下和向上取整的整数之间的差的绝对值,与哪个的差值小就选哪个作为真正的bests,如果差值相等,说明有两个整数最优解,按照题目要求输出0。还要注意一点,如果在s=bests时函数值为负数,这种情况是无解的,因为原式没有意义。
所以总归来说这题还是很水的......完全是初中知识嘛,写起代码来也是只有20多行,多年前的NOI果然水啊。
以下是本人代码:
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cmath>
#define e 1e-7
using namespace std;
double vt,v0,best,c,ans;
int main()
{
scanf("%lf%lf",&vt,&v0);
best=vt/(2*v0);
c=(int)best+0.5;
if (fabs(best-c)<e) {printf("0");return 0;}
else if (best<c) best=(int)best;
else best=(int)best+1;
ans=0.3*best*sqrt(vt/best-v0);
if (ans<0) printf("0");
else printf("%.0lf",best);
return 0;
}