空得较多的数学公式那里有一个根号,不知道为什么显示不出来
题目链接:https://www.luogu.com.cn/problem/UVA1356
题目表面意思很简单。
首先我们可以很轻易地求出抛物线的个数
c
n
t
cnt
cnt
然后可以得到每个抛物线的最长长度
l
e
n
len
len
设抛物线顶点到最高点高度为
h
h
h
接着需要一个引理:
可导函数
f
(
x
)
f(x)
f(x)定义在
(
c
,
d
)
(c,d)
(c,d)上, 平面直角坐标系上[a,b]上的弧长为
∫
a
b
1
+
[
f
′
(
x
)
]
2
d
x
\int_a^b\sqrt{1+[f'(x)]^2}dx
∫ab1+[f′(x)]2dx
证明:令
S
(
t
)
S(t)
S(t)为
c
c
c至
t
t
t的弧长
则:
d
s
=
lim
Δ
t
→
0
S
(
t
+
Δ
t
)
−
S
(
t
)
=
Δ
t
2
+
[
f
(
t
+
Δ
t
)
−
f
(
t
)
]
2
ds=\lim_{\Delta t \to \ 0}S(t+\Delta t)-S(t)=\sqrt{{\Delta t}^2+[f(t+\Delta t)-f(t)]^2}
ds=Δt→ 0limS(t+Δt)−S(t)=Δt2+[f(t+Δt)−f(t)]2
通俗的说就是当变化量趋近于
0
0
0时弧长趋近于位移
这样我们就可以用微分推出导数:
s
′
(
x
)
=
1
+
[
f
′
(
x
)
]
2
s'(x)=\sqrt{1+[f'(x)]^2}
s′(x)=1+[f′(x)]2
至于求
s
(
x
)
s(x)
s(x)积个分就好了
然后对于抛物线的高度,我们可以列出二次函数表达式
f
(
x
)
=
4
h
l
e
n
2
x
2
f(x)=\frac{4h}{len^2}x^2
f(x)=len24hx2
发现
f
′
(
x
)
f'(x)
f′(x)关于
h
h
h单调递增
二分求解,再用自适应自适应辛普森积分求积分即可
自适应辛普森积分(my blog)
C o d e Code Code
#include <bits/stdc++.h>
using namespace std;
const double EPS = 1e-6;
double a, len;
inline int read();
double get_ans(double);
inline double f(double);
inline double simpson(double, double);
double asr(double, double, double, double);
int main(){
//freopen ("std.in","r",stdin);
//freopen ("std.out","w",stdout);
int t, Case = 1;
scanf("%d", &t);
while (t--){
int d,h,b,L;
scanf("%d%d%d%d", &d, &h, &b, &L);
int cnt = (b + d - 1) / d;
len = b / (double)cnt;
double l = 0, r = h;
while ((r - l) >= EPS){
double mid = (l + r) / 2.0;
if (get_ans(h - mid) * cnt < (double)L) r = mid;
else l = mid;
}
if (Case > 1) printf("\n");
printf("Case %d:\n", Case++);
printf("%.2f\n", l);
}
return 0;
}
double get_ans(double h){
a = 4 * h / len / len;
return 2 * asr(0, len / 2.0, EPS, simpson(0, len / 2.0));
}
double asr(double a, double b, double eps, double A){
double c = (a + b) / 2;
double l = simpson(a, c), r = simpson(c, b);
if (fabs(l + r - A) <= 15 * eps) return l + r + (l + r - A) / 15.0;
return asr(a, c, eps / 2.0, l) + asr(c, b, eps / 2.0, r);
}
inline double f(double x){
return sqrt(1 + 4 * a * a * x * x);
}
inline double simpson(double a, double b){
return (f(a) + f(b) + 4 * f((a + b) / 2) ) * (b - a) / 6;
}