uvalive 3485 - 数值积分

/**
抛物线积分求曲线长度。
首先确定出桥墩的个数。
题目要求桥墩数量要最少,也就是看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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值