HDU2899 Strange fuction

题意:求连续函数并且是凹函数的最小值

法一:‘

三分查找:

#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 压过。好吧慢一些,而且证明很蛋疼,虽然写的时候根本没想那么多,写博客才突然想起来,高中数学不好。。。。。。

你可能感兴趣的:(HDU2899 Strange fuction)