-导数- [洛谷 P5515][MtOI2019]灵梦的计算器

题目描述

Link

Solution

前置知识:导数

你需要了解导数的含义和一些初等函数的导数。

让我们先来用几何画板模拟一下这个题中的一个函数。

我们会发现如果 $a,b​$ 都在所归定的数据范围内,这个函数图像形状很像二次函数,并且这个函数增长速度非常快。

我们设满足题意的最小 $n’$ 为 $a_1$ ,满足题意的最大 $n’$ 为 $a_2$。

所以 $f(a_1) - f(a_2) < 1​$。

我们可以任取两个 $f(a_1),f(a_2)​$ 来观察一下。

又可以发现这几个点围成了一个三角形的图案。

可能这时候有人会说:函数图像明明是曲线啊,怎么可能会是直线呢?

是的,确实是曲线,但是,用题目中所给的数据计算的话,得出的答案很大,已经到了可以忽略曲率的地步,并且题目要求的精度也不高,所以我们能够直接把这段函数图像看成直线。

但是为题又来了,该如何求它的斜率呢?

这时候,我们就需要用到导数了!

因为导数所求的是在函数任意一点处的斜率,而又因为 $f(n)​$ 一定在这段函数图像上,所以我们可以直接把 $f’(n)​$ 当做这个三角形斜边的斜率。

最后就可以得出答案 $a_2 - a_1 = \frac{0.999}{f’(n)}​$。

上代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
namespace Mker {
#define uint unsigned int
uint sd;
int op;
inline void init() {
scanf("%u %d", &sd, &op);
}
inline uint uint_rand() {
sd ^= sd << 13;
sd ^= sd >> 7;
sd ^= sd << 11;
return sd;
}
inline double get_n() {
double x = (double) (uint_rand() % 100000) / 100000;
return x + 4;
}
inline double get_k() {
double x = (double) (uint_rand() % 100000) / 100000;
return (x + 1) * 5;
}
inline void read(double &n,double &a, double &b) {
n = get_n();
a = get_k();
if (op) b = a;
else b = get_k();
}
}
using namespace Mker;
int T;
double n, a, b, k, ans;
int main() {
scanf("%d", &T);
init();
while (T--) {
read(n, a, b);
k = a * pow(n, a - 1) + b * pow(n, b - 1);
ans += 0.9999999 / k;
}
printf("%0.5f", ans);
}
文章作者: RiverFun
文章链接: https://stevebraveman.github.io/blog/2019/08/24/99/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 RiverFun

评论