二分圆弧半径,使弦长对应的圆弧长度等于热胀后的木棍长度。
OJ: noi_openjudge
题目 ID: ch0111-09
难度:普及+/提高
标签:二分几何python
日期: 2026-07-30 23:01
题意
木棍受热后长度增加,但两端仍固定在原位置。把它看成圆弧,求圆弧中点相对原直线的偏移量。
思路
热胀后的弧长为
代码
Python代码
python
from math import asin, sqrt
length, temperature_change, coefficient = map(float, input().split())
expanded_length = length * (1 + temperature_change * coefficient)
if expanded_length == length:
print("0.000")
else:
# 半径越大,对应的圆弧越接近弦,弧长越小。
low, high = length / 2, 1e18
for _ in range(200):
radius = (low + high) / 2
arc_length = 2 * radius * asin(length / (2 * radius))
if arc_length > expanded_length:
low = radius
else:
high = radius
radius = (low + high) / 2
offset = radius - sqrt(radius * radius - (length / 2) ** 2)
print(f"{offset:.3f}")C++代码
cpp
#include <cstdio>
int l,n,m;
int _min = 0x7f7f7f7f;
int a[50005];
void init(){
scanf("%d%d%d",&l,&n,&m);
int i;
for (i=1;i<=n;i++){
scanf("%d",&a[i]);
if( _min > a[i]-a[i-1])
_min = a[i]-a[i-1];
}
if( l - a[n] < _min)
_min = l - a[n];
a[n+1] = l;
}
int cnt_remove(int num){
int i,cnt = 0;
int pre = 0;
for(i=1;i<=n;i++){
if( a[i] - a[pre] < num){
cnt++;
}
else{
pre = i;
}
}
if( l-a[pre] < num)
cnt++;
return cnt;
}
//查找范围是[l,r), a[r] 永远 > key
template <typename T>
int first_g(T a[],int l,int r){
int mid;
while( l != r ) //表示l和r没有重合
{
mid = (l+r) >>1; // 取中间位置
if(cnt_remove(mid) <= m ) //表示 [m+1,r) 满足条件
l = mid+1;
else
r = mid;
}
return l;
}
int main(){
init();
int ans = first_g(a,_min , l);
printf("%d\n",ans-1);
return 0;
}复杂度
固定进行 200 次二分,时间复杂度和空间复杂度均为
总结
圆弧模型把“热胀弯曲”转化为单调的几何方程,适合实数二分。