/**
抛物线积分求曲线长度。
首先确定出桥墩的个数。
题目要求桥墩数量要最少,也就是看D是不是能被总长度B整除,
若可以则桥墩数量n = B/D,
否则 n = B/D + 1, 一个简化的写法就是 直接n = (D+B-1)/D
确定了数量就可以求出桥墩之间的距离w = B/n
同时可以求出,相邻桥墩之间绳子长度dl = L/n
设抛物线方程为y = a*x*x.
显然当a越大时,抛物线长度越小,出现了单调性!
二分a,解出当a为何值是绳子长度为dl,
最后计算抛物线右端点的高度和桥的高度差就是最后答案!
**/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <cmath>
#include <algorithm>
#include <functional>
using namespace std;
const int inf = 1<<28;
const double eps = 1e-10;
int D,H,B,L;
// log() 以e为底的对数
double f(double x){
return (2*x*sqrt(1+x*x) + log( (sqrt(1+x*x) + x) / (sqrt(1+x*x) - x)) )*0.25;
}
double calc(double m,double w){
return ( f(2.0*m*w) - f(-2.0*m*w) )/2.0/m;
}
int dcmp(double x){
if(fabs(x) < eps) return 0;
if(x > 0) return 1;
return -1;
}
int main(){
int T,nCase = 1;
cin >> T;
while(T--){
cin >> D >> H >> B >> L;
int n = (B+D-1)/D;
double w = (double) B/n/2.0;
double dl = (double) L/n;
double l = 0, r = inf, m;
for(int i=0;i<100;i++){
m = (l+r)/2.0;
double len = calc(m,w);
//cout << m << " " << len << " " << dl << endl;
if(dcmp(len - dl) == 1) r = m;
else l = m;
}
double ans = H*1.0 - m*w*w;
printf("Case %d:\n",nCase++);
printf("%.2lf\n",ans);
if(T) puts("");
}
return 0;
}
uvalive 3485 - 数值积分
最新推荐文章于 2022-02-08 10:23:03 发布