信息学奥赛一本通 1246:膨胀的木棍 | OpenJudge NOI 1.11 09:膨胀的木棍

【题目链接】

ybt 1246:膨胀的木棍
OpenJudge NOI 1.11 09:膨胀的木棍
该题数据比较刁钻,只有下面给的第一种写法在两个OJ上都能过。大概理解就行,不用扣为什么我的写法符合逻辑但过不了。

【题目考点】

1. 二分:实数域二分查找

题目要求保留到小数点后m位,在循环时要写为while(r - l >= 1e-(m+1))
比如要求保留到小数点后2位,l和r间的距离要在小于1e-3时才能停止循环。

【解题思路】

解法1:二分求 α \alpha α

根据题目公式 L ′ = ( 1 + n ∗ C ) ∗ L L'=(1+n*C)*L L=(1+nC)L求出 L ′ L' L
圆心角 ∠ A O B 的大小 α \angle AOB 的大小\alpha AOB的大小α最小为0,最大为 π \pi π
二分查找合适的 α \alpha α
因为 s i n α 2 = L 2 r sin\frac{\alpha}{2} = \frac{L}{2r} sin2α=2rL
所以 r = L 2 s i n α 2 r = \frac{L}{2sin\frac{\alpha}{2}} r=2sin2αL
求出 A B ⌢ \overset{\frown}{AB} AB长为 α r = α L 2 s i n α 2 \alpha r = \frac{\alpha L}{2sin\frac{\alpha}{2}} αr=2sin2ααL
比较 α r \alpha r αr L ′ L' L

  • 如果 α r \alpha r αr L ′ L' L大,那么下一次 α \alpha α要小一点,取左半边区间
  • 如果 α r \alpha r αr L ′ L' L小,那么下一次 α \alpha α要大一点,取右半边区间

求出 α \alpha α后,先求 r = L ′ α r = \frac{L'}{\alpha} r=αL(理论上也可以用 r = L 2 s i n α 2 r = \frac{L}{2sin\frac{\alpha}{2}} r=2sin2αL,但实际使用的话会WA,也许是由于计算太多了导致精度不正确),再求 O P = r ⋅ c o s α 2 OP = r\cdot cos\frac{\alpha}{2} OP=rcos2α,最后 x = r − O P = r − r ⋅ c o s α 2 = r ( 1 − c o s α 2 ) x = r - OP = r-r\cdot cos\frac{\alpha}{2} = r(1-cos\frac{\alpha}{2}) x=rOP=rrcos2α=r(1cos2α)

解法2:二分求x
1. 已知x求 A B ⌢ \overset{\frown}{AB} AB弧长

如图所示,已知线段 A B AB AB长为 L L L A B ⌢ \overset{\frown}{AB} AB长为 L ′ L' L L ′ L' L的长度可以通过题中给的公式求出。 A B ⌢ \overset{\frown}{AB} AB所对的圆心角为 α \alpha α,线段 M P MP MP长为 x x x,也就是要求的木棍中心的偏移距离。该弧的半径是 r r r
P O PO PO长为 r − x r - x rx A P AP AP L 2 \frac{L}{2} 2L △ A P O \triangle APO APO是直角三角形,根据勾股定理,有:
( r − x ) 2 + ( L 2 ) 2 = r 2 (r-x)^2+(\frac{L}{2})^2 = r^2 (rx)2+(2L)2=r2
化简得
r = 4 x 2 + L 2 8 x r = \frac{4x^2+L^2}{8x} r=8x4x2+L2
∠ A O P \angle AOP AOP 的正弦值:
s i n α 2 = L 2 r sin\frac{\alpha}{2} = \frac{L}{2r} sin2α=2rL
所以有:
α = 2 a r c s i n ( L 2 r ) \alpha = 2arcsin(\frac{L}{2r}) α=2arcsin(2rL)
所以 A B ⌢ \overset{\frown}{AB} AB长度为 α r \alpha r αr

2. x的范围

x最小时为0,此时木棍不膨胀, L ′ L' L 等于 L L L
x越大, L ′ L' L越大
x最大时近似为r。题目说 L ′ L' L最大为L的1.5倍,当该弧为半圆时, r = L 2 r = \frac{L}{2} r=2L,弧长
π r = π 2 L ≈ 1.57 L \pi r = \frac{\pi}{2}L \approx1.57L πr=2πL1.57L,比题目中给定的x最大时的情况要大。

3. 二分求x

通过二分法取x,取到x后根据上面第1点中的方法求出 A B ⌢ \overset{\frown}{AB} AB的长度。而后与通过题目给定的膨胀系数公式求出的 L ′ L' L进行比较。
如果求出的 A B ⌢ \overset{\frown}{AB} AB的长度比 L ′ L' L长,说明x取大了,下一次取左半边区间。
如果求出的 A B ⌢ \overset{\frown}{AB} AB的长度比 L ′ L' L小,说明x取小了,下一次取右半边区间。

【题解代码】

解法1:二分求 α \alpha α
#include <bits/stdc++.h>
using namespace std;
#define PI acos(-1)
double l, c, n, l1;
double getArcAB(double a)
{
    return l*a/(2*sin(a/2));
}
int main() 
{
	cin >> l >> n >>c;
	l1 = (1+n*c)*l;
	double left = 0, right = PI, mid;
	while(right - left >= 1e-12)
	{
	    mid = (left + right) / 2;
	    if(getArcAB(mid) < l1)
	       left = mid;
	    else
	       right = mid;
    }
    cout << fixed << setprecision(3) << l1/mid*(1-cos(mid/2));
	return 0;
}

if(getArcAB(mid) < l1)这句,如果写<=,在OpenJudge上就不过,在ybt上能过。或者最后输出l/(2*sin(mid/2))*(1-cos(mid/2)),在OpenJudge上能过,在ybt上过不了。这东西没什么道理,就是两个OJ的数据点不同。理解题意的逻辑就行,扣这些细节没意义。

解法2:二分求x

该解法在信息学奥赛一本通OJ上过不了。在OpenJudge上能过。

#include <bits/stdc++.h>
using namespace std;
double l, c, n, l1;
double getArcAB(double x)//通过几何求出的弧长 
{
    double r, a;
    r = (4*x*x+l*l)/(8*x);
    a = 2*asin(l/(2*r));
    return a*r;  
}
int main() 
{
	cin >> l >> n >>c;
	l1 = (1+n*c)*l;
	double left = 0, right = l, mid;
	while(right - left >= 1e-4)
	{
	    mid = (left + right) / 2;
	    if(getArcAB(mid) > l1)
	       right = mid;
	    else
	       left = mid;
    }
    cout << fixed << setprecision(3) << mid;
	return 0;
}
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值