题意:求连续函数并且是凹函数的最小值
法一:‘
三分查找:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
using namespace std;
double Y;
double ans(double x)
{
return 6*pow(x, 7) + 8*pow(x, 6) + 7*pow(x, 3) + 5*pow(x, 2) - Y*x;
}
int main()
{
//freopen("in.txt", "r", stdin);
int T;
double l, r, lmid, rmid;
cin>>T;
while(T--){
cin>>Y;
l = 0, r = 100;
while(fabs(l-r) > 1e-7){
lmid = (l + r)/2.0;
rmid = (r + lmid)/2.0;
if(ans(lmid) < ans(rmid)){
r = rmid;
}
else{
l = lmid;
}
}
printf("%.4f\n", ans(l));
}
}
0 ms飘过。第一次做三分搜索的题。
法二:
由于求的是最小值,而且是连续函数,在极值点的导数值为0。
而且我猜测试数据的最小值一定出现在极小值点,而且在0<=x<=100一定有满足条件的极小值点。
好吧,我们来估计一下:
首先:0<Y<1e10,0<=x<=100,而导数为f'(x) = 42*x^6 + 48*x^5 + 21*x^2 + 10*x -Y;
明显 42*x^6 + 48*x^5 + 21*x^2 + 10*x 的取值在0与42*100^6之间,上限要大一些,但这已经远远大于1e10 了。
所以无论Y取何值,左边部分总存在比Y小和比Y大的,而且是连续函数,还是先小后大,所以一定会有极小值。
于是我们就可以愉快地用二分法了:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
using namespace std;
double Y;
double der(double x)
{
return 42*pow(x, 6) + 48*pow(x, 5) + 21*pow(x, 2) + 10*x;
}
double ans(double x)
{
return 6*pow(x, 7) + 8*pow(x, 6) + 7*pow(x, 3) + 5*pow(x, 2) - Y*x;
}
int main()
{
// freopen("in.txt", "r", stdin);
int T;
double l, r, mid;
cin>>T;
while(T--){
cin>>Y;
l = 0, r = 100;
while(fabs(der(mid) - Y) > 1e-7){
mid = (l + r)/2;
if(der(mid) > Y){
r = mid;
}
else{
l = mid;
}
}
printf("%.4f\n", ans(mid));
}
}
但是15 ms 压过。好吧慢一些,而且证明很蛋疼,虽然写的时候根本没想那么多,写博客才突然想起来,高中数学不好。。。。。。