2022广西师范大学暑期训练赛 B.签到在这里

B.签到在这里

标签:求导,二分

题意:给定一个函数 f ( x ) f(x) f(x),共有m组数据,每组数据给出函数里的系数a,b,c,d,e,在定义域内求出 f ( x ) f(x) f(x)的最小值,若最小值趋近于负无穷,输出INF
f ( x ) = a x 2 + b x + c + G ( x ) f(x) = ax^2 + bx + c + G(x) f(x)=ax2+bx+c+G(x)
G ( x ) = d ∗ g ( x ) 2 + e ∗ g ( x ) G(x) = d*g(x)^2 + e*g(x) G(x)=dg(x)2+eg(x)
g ( x ) = l o g 2 ( x ) , x ∈ ( 0 , 1 0 6 ] g(x) = log2(x), x\in(0,10^6] g(x)=log2(x),x(0,106]

题解

梦回高中导数题

首先对于INF的情况,只有当 x x x趋近于0的时候, g ( x ) g(x) g(x)趋近于负无穷,所以当d = 0且e != 0的时候, f ( x ) f(x) f(x)的最小值趋近于负无穷,此时输出INF

然后正常求函数最小值,我们发现 f ( x ) f(x) f(x)由一个二次函数(虽然a = 0和b = 0的情况不是二次函数,但一定有最小值,所以直接当成二次函数处理)和 G ( x ) G(x) G(x)构成。

二次函数的系数非负,那么它的图像是先减后增的,有最小值。

G ( x ) G(x) G(x)求导得到 G ′ ( x ) G'(x) G(x) = 2 d l o g 2 ( x ) + e x l n 2 2dlog2(x)+ e\over xln2 xln22dlog2(x)+e,再求一次二阶导发现 G ′ ′ ( x ) G''(x) G′′(x)大于0,所以 G ′ ( x ) G'(x) G(x)单调递增,取值代入发现 G ′ ( x ) G'(x) G(x)先负后正,存在一个零点 x 0 x0 x0,所以 G ( x ) G(x) G(x)的图像也是先减后增的,在 x 0 x0 x0处取得最小值。

这两个函数相加也是类似于先减后增的情况,有最小值,那么我们需要对 f ( x ) f(x) f(x)求导,得 f ′ ( x ) f'(x) f(x) = 2 a x + b + 2 d l o g 2 ( x ) + e x l n 2 2ax + b + 2dlog2(x)+ e\over xln2 xln22ax+b+2dlog2(x)+e,由于xln2大于0,乘上xln2不会影响正负,为了减小误差,我们可以直接分析 f f ( x ) = 2 a l n 2 x 2 + b l n 2 x + 2 d l o g 2 ( x ) + e ff(x) = 2aln2x^2 + bln2x + 2dlog2(x) + e ff(x)=2aln2x2+bln2x+2dlog2(x)+e,对 f f ( x ) ff(x) ff(x)二分找出零点 x 1 x1 x1,那么 f ( x 1 ) f(x1) f(x1)即为答案

代码实现

#include <algorithm>
#include <iostream>
#include <stdio.h>
#include <iomanip>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <math.h>
#define ll long long
#define fst ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const double eps = 1e-12;
int t, m, a, b, c, d, e;
double G(double x){
    return d * log2(x) * log2(x) + e * log2(x);
}
double f(double x){
    return  a * x * x + b * x + c + G(x);
}
double ff(double x){
    return 2 * a * log(2) * x * x + b * log(2) * x + 2 * d * log2(x) + e;
}
int main(){
    cin >> t;
    while(t--){
        cin >> m;
        while(m--){
            cin >> a >> b >> c >> d >> e;
            if(d == 0 && e){
                cout << "INF" << "\n";
                continue;
            }
            double l = 1e-7, r = 1e6;
            while(r - l >= eps){
                double mid = (l + r) / 2;
                if(ff(mid) < 0) l = mid;
                else r = mid;
            }
            cout << f(r) << "\n";
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值