1 条题解
-
0
思路与算法
设圆心角的一半为θ,弦长L=2Rsinθ,弧长L′=2Rθ,因此sinθ/θ=1/(1+d),d=nC。短弧θ∈[0,π/2],对loss(θ)=1−sinθ/θ二分,使其等于d/(1+d)。最终弓高h=(L/2)tan(θ/2)。很小角度直接相减会丢精度,此时用θ²/6−θ⁴/120+θ⁶/5040−…计算loss。L=0或d=0直接输出0。
正确性说明
圆弧与弦长关系导出上述方程。对0<θ≤π/2,sinθ−θcosθ的导数为θsinθ>0,故θ/sinθ严格递增,loss也严格递增。d≤0.5时所需弧弦比≤1.5<π/2,唯一解落在二分区间。每次按loss比较保留包含真解的一半;120步后二分误差足够小。h=R(1−cosθ)用半角式改写,避免小角相减。小角级数为交错递减项,20项截断远小于公开误差;long double计算与三位输出满足约定容差。
复杂度
初始化O(1),120次二分,每次至多20项级数或一次正弦,均为固定次数,总时间O(1),额外空间O(1)。若按目标二分精度δ计,为O(log(1/δ))次判定。
易错点
圆弧不是抛物线;所求为弓高,不是半径。L0和零膨胀单独处理。微小d下1−sinθ/θ会抵消,应采用级数;输出使用题面公开绝对误差,不机械逐字比较舍入串。
参考代码(C++11)
#include <bits/stdc++.h> using namespace std; long double loss(long double theta) { if (theta < 0.01L) { long double q = theta * theta, term = q / 6, sum = term; for (int k = 2; k <= 20; k++) { term *= -q / ((2 * k) * (2 * k + 1)); sum += term; } return sum; } return 1 - sinl(theta) / theta; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); long double L, n, C; cin >> L >> n >> C; long double d = n * C; if (L == 0 || d == 0) { cout << "0.000\n"; return 0; } long double target = d / (1 + d), lo = 0, hi = acosl(-1.0L) / 2; for (int i = 0; i < 120; i++) { long double mid = (lo + hi) / 2; if (loss(mid) < target) lo = mid; else hi = mid; } long double theta = (lo + hi) / 2; cout << fixed << setprecision(3) << L / 2 * tanl(theta / 2) << '\n'; }
- 1