弧长与弦长固定时圆心角唯一,二分求角后代弓形高公式输出偏移。
OJ: roj
题目 ID: 1246
难度:普及-
标签:数学二分计算几何python
创建: 2026-09-30 01:32
更新: 2026-10-07 12:15
题目描述
木棍原长
输入:三个非负实数
样例输入:1000 100 0.0001,样例输出:61.329。
思路
由
参考代码
Python 版:
python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-09-30 01:33
# update_at: 2026-09-30 01:38
import sys
from math import sin, cos
EPS = 1e-12 # 二分终止精度:角度差小于它就不再细分(与 std.cpp 的 E 一致)
def solve() -> None:
data = iter(map(float, sys.stdin.buffer.read().split()))
length, n, c = next(data), next(data), next(data) # 原长、温度变化、热膨胀系数
expanded = (1 + n * c) * length # 受热后的弧长 L'
# 圆心角 θ 唯一:半径 r = L'/θ,弦长 2r·sin(θ/2),要求弦长恰等于原长 L。
# 弦长关于 θ 严格递减(θ→0 时弦→弧长 L',θ=π 时弦=2L'/π 的最小值),可二分。
lo, hi = 0.0, 3.15 # 上界取略大于 π 即可覆盖弧长 ≤ 1.5L 的全部情形
while hi - lo > EPS:
mid = (lo + hi) / 2
chord_too_long = 2 * expanded * sin(mid / 2) / mid > length # 该角度下的弦长
if chord_too_long:
lo = mid # 弦偏长说明还不够弯,角度要变大
else:
hi = mid
# 中心偏移 = 弓形高 = r - r·cos(θ/2),其中 r = L' / θ
radius = expanded / hi
print(f"{radius * (1 - cos(hi / 2)):.3f}")
if __name__ == "__main__":
solve()C++ 版(同一算法):
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-10-05 06:54
* update_at: 2026-10-05 06:54
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double EPS = 1e-12; // 二分终止精度,远超三位小数输出要求
double L, n, C; // 木棍原长、温度变化、热膨胀系数
// 输入为一个浮点数序列,直接读入即可。
void read_input() {
cin >> L >> n >> C;
}
// 核心:弧长 L' = (1+n*C)*L 固定,弦长 = L 固定,圆心角 θ 唯一。
// 由 r = L'/θ 与 L = 2*r*sin(θ/2) 消去 r,得到方程 2*L'*sin(θ/2)/θ = L。
// 左端在 (0,π] 严格递减,且 g(0+) = L' ≥ L,g(π) < L,故可二分 θ。
void solve() {
double expanded = (1.0 + n * C) * L; // 受热后的弧长 L'
double lo = 0.0, hi = 3.15; // 上界略大于 π 即可
while (hi - lo > EPS) {
double mid = (lo + hi) / 2.0;
double chord = 2.0 * expanded * sin(mid / 2.0) / mid; // 当前 θ 对应的弦长
if (chord > L) {
lo = mid; // 弦偏长 => 还不够弯 => 角度调大
} else {
hi = mid; // 弦偏短/相等 => 角度调小
}
}
double theta = hi; // 最终圆心角
double radius = expanded / theta; // 半径 r = L'/θ
double h = radius * (1.0 - cos(theta / 2.0)); // 弓形高 = r - r*cos(θ/2)
cout << fixed << setprecision(3) << h << "\n";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
read_input();
solve();
return 0;
}