题意:求连续函数并且是凹函数的最小值
法一:‘
三分查找:
#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 压过。好吧慢一些,而且证明很蛋疼,虽然写的时候根本没想那么多,写博客才突然想起来,高中数学不好。。。。。。