REAL688 小红的函数最大值
题目链接
题目描述
给定函数 ,其中
为正整数,定义域为
。
输入参数范围:
求该函数在定义域上的最大值。
解题思路
这是一个经典的函数求最值问题,可以通过微积分来解决。
-
函数与定义域
函数为
。对数函数的定义域要求
。为了方便求导,我们使用换底公式将
转换为以自然对数
为底:
-
求导以寻找极值点
为了找到函数的最大值,我们首先需要找到其导数
,并令其等于零,以确定函数的驻点(critical points)。
令
,解出
:
这是函数唯一的驻点。
-
判断极值类型(二阶导数法)
为了确定这个驻点是极大值点还是极小值点,我们求解二阶导数
:
由于
,所以
。在定义域
内,
也恒为正。因此,
恒小于 0。
二阶导数恒为负,说明函数是严格的凹函数(concave down),因此我们找到的唯一驻点必定是函数的全局最大值点。
-
计算最大值
将取得最大值时的
代入原函数
:
代码实现时,直接根据这个公式计算即可。
代码
#include <iostream>
#include <cmath>
#include <iomanip>
// C++ Solution
void solve() {
double a, b;
std::cin >> a >> b;
// 根据公式直接计算
// f_max = -(log(b) + log(log(a)) + 1) / log(a)
// C++ 中 log() 就是自然对数 ln()
double log_a = std::log(a);
double result = -(std::log(b) + std::log(log_a) + 1.0) / log_a;
std::cout << std::fixed << std::setprecision(10) << result << std::endl;
}
int main() {
solve();
return 0;
}
import java.util.Scanner;
import java.lang.Math;
// Java Solution
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
double a = sc.nextDouble();
double b = sc.nextDouble();
// 根据公式直接计算
// f_max = -(Math.log(b) + Math.log(Math.log(a)) + 1) / Math.log(a)
// Java 中 Math.log() 就是自然对数 ln()
double logA = Math.log(a);
double result = -(Math.log(b) + Math.log(logA) + 1.0) / logA;
System.out.printf("%.10f\n", result);
}
}
import math
# Python Solution
def solve():
try:
a, b = map(int, input().split())
# 根据公式直接计算
# f_max = -(math.log(b) + math.log(math.log(a)) + 1) / math.log(a)
# Python 中 math.log() 就是自然对数 ln()
log_a = math.log(a)
result = -(math.log(b) + math.log(log_a) + 1.0) / log_a
print(f"{result:.10f}")
except (ValueError, EOFError):
pass
if __name__ == "__main__":
solve()
算法及复杂度
-
算法:数学/微积分
-
时间复杂度:
。
- 代码只涉及几次对数函数调用和基本的算术运算,其时间复杂度为常数。
-
空间复杂度:
。
- 只需要常数级别的额外空间存储输入和中间变量。