uvalive 3485 - 数值积分

来源:互联网 发布:阿里云ecs搭建ss 编辑:程序博客网 时间:2024/05/17 18:16
/**抛物线积分求曲线长度。首先确定出桥墩的个数。题目要求桥墩数量要最少,也就是看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;}


0 0