「一本通 1.2 练习 3」灯泡(三分/公式法)(三角函数,计算几何)

传送门

在这里插入图片描述

这道题要用带一点点三角函数。。。

不用怕,只要有理性的思维,是可以知道怎么做的

度娘!
在这里插入图片描述

说说我对三角函数的理解吧,简单来说,就是如果你知道直角三角形的一个锐角,那你就知道了这个直角三角型的形状了(求出三个角的角度数),那么如果由另一个直角三角型的三个角也跟这个三角形相等,那么他们两个是可以通过比例转化的,他们三条边中任意两条边之比也相等(也就是任意两条边之比如果角的度数固定了,那么这俩条边的比就固定了)。

安利:
在这里插入图片描述

那么,假设人的影子没有在墙上,那么,人从灯底往右走,走越远影子越长!那么最长的情况就是这样:
在这里插入图片描述

由于比相同,设影长为L,设人离灯x米远。
H:D=h:LH:D=h:L
Dh=HL所以Dh=HL
Dh/H=LDh/H=L

那么我们得出了,在影子全在地上,L的最大值为Dh/H,这时x为D-Dh/H,设left=D-Dh/H
那么,如果影子全在墙上,则L=h,x=D,设right为D。
如果影子在墙上,就比较抽象了。。。

在这里插入图片描述
然后呢。。。?
在这里插入图片描述

那么:
在这里插入图片描述
Hh:x=kk:(Dx)那么(H-h):x=kk:(D-x)
(Hh)(Dx)=xkk(H-h)*(D-x)=x*kk
(Hh)(Dx)/x=kk(H-h)*(D-x)/x=kk
那么在墙上的影子就是
hkk=h(Hh)(Dx)/x=H(Hh)D/xh-kk=h-(H-h)*(D-x)/x=H-(H-h)*D/x
L=Dx+(hkk)=Dx+H(Hh)D/xL=D-x+(h-kk)=D-x+H-(H-h)*D/x
=D+H(x+(Hh)D/x)=D+H-(x+(H-h)*D/x)

那么就是要让x+(Hh)D/xx+(H-h)*D/x取最小值,可以证明,在正数区间,x+(Hh)D/xx+(H-h)*D/x是个开口向上的单峰函数。

证:
情况1:x增加y,(Hh)D/x(H-h)*D/x减小的数大于y
情况2:x增加y,(Hh)D/x(H-h)*D/x减小的数小于y
又由于x越大,(Hh)D(H-h)*D/x减小的数字越小,所以,会由情况1慢慢转为情况2,于是便由下降变为上升,成单峰势。

于是,D+H(x+(Hh)D/x)D+H-(x+(H-h)*D/x)便是个开口向下的单峰函数!(那你整这么一大坨有什么用?)
在这里插入图片描述
早说有图片!

实现:
l=left,r=right;
当答案=l时,代表影子全在地上的最大值。
当答案=r是时,代表影子全在墙上的最大值
当答案=(l,r)时,代表影子一半在墙上,一半在地上的最大值。

代码:

#include<cstdio>
#include<cstring>
using  namespace  std;
typedef  long  long  ll;
inline  double  mymax(double  x,double  y){return  x>y?x:y;}
inline  double  cai(double  H,double  h,double  D,ll  x)
{
	double  xx=x/10000.0;
	return  H+D-xx-((H-h)*D)/xx;
}//之前推出的函数 
double  sanfen(double  H,double  h,double  D)
{
	ll  l=ll((D-(h*D)/H)*10000.0),r=ll(D*10000.0);//乘以10000转ll 
	ll  m1,m2;
	while(l<r)//三分 
	{
		m1=(l+r)/2;m2=(l+r)/2+1;
		if(cai(H,h,D,m1)>cai(H,h,D,m2))r=m1;
		else  l=m2;
	}
	return  cai(H,h,D,l);//真象只有一个,l或r就是答案 
}
int  main()
{
	int  T;scanf("%d",&T);
	while(T--)
	{
		double  H,h,D;scanf("%lf%lf%lf",&H,&h,&D);
		printf("%.3lf\n",sanfen(H,h,D));//输出 
	}
	return  0;
}

公式法:

因为这个我看了好久题解(泪奔)(:光速逃

那么,如果是经验丰富的巨佬,一定会想到公式法。。。

(Hh)DABCDx我们设(H-h)*D为A,设B、C、D为x的一个取值。
Cx+(Hh)D/xC为x+(H-h)*D/x的单峰
B&lt;C&lt;D且B&lt;C&lt;D
B+A/B&gt;C+A/C&lt;D+A/D则有B+A/B&gt;C+A/C&lt;D+A/D
B+A/B&gt;C+A/C由B+A/B&gt;C+A/C所得
BC&gt;A/CA/BB-C&gt;A/C-A/B
BC&gt;A(BC)/BCB-C&gt;A(B-C)/BC
BC(BC)&gt;A(BC)BC(B-C)&gt;A(B-C)
BC&lt;ABC&lt;A
C&lt;BBC&lt;C2又因为C&lt;B,所以BC&lt;C^2
那是不是代表A=C2A=C^2~~证出来了,耶!~~想太多

安利:
在这里插入图片描述

C+A/C&lt;D+A/D但是,由C+A/C&lt;D+A/D可得
CD&lt;A/DA/CC-D&lt;A/D-A/C
CD&lt;A(CD)/CDC-D&lt;A(C-D)/CD
CD(CD)&lt;A(CD)CD(C-D)&lt;A(C-D)
CD&gt;ACD&gt;A
D&gt;C,CD&gt;C2又因为D&gt;C,所以CD&gt;C^2
那么我们就可以名正言顺说A=C2A=C^2耶!
所以C=sqrt(A)C=sqrt(A)
所以,当xx等于sqrt((Hh)D)sqrt((H-h)*D)时,x+(Hh)D/xx+(H-h)*D/x位於单峰上,同时D+H(x+(Hh)D/x)D+H-(x+(H-h)*D/x)也位於单峰上
在这里插入图片描述

当然,当x&lt;=leftx&lt;=left时,由于D+H(x+(Hh)D/x)D+H-(x+(H-h)*D/x)是个开口向下的单峰函数,且x=[left,right]x=[left,right]所以x=left。
同理当x&gt;=rightx&gt;=right时,x=right!

代码:

#include<cstdio>
#include<cstring>
#include<cmath>
using  namespace  std;
int  main()
{
	int  T;scanf("%d",&T);
	while(T--)
	{
		double  H,h,D;scanf("%lf%lf%lf",&H,&h,&D);
		double  x=sqrt((H-h)*D);
		if(x<=D-(h*D)/H)printf("%.3lf\n",(h*D)/H);//全在地上
		else  if(x>=D)printf("%.3lf\n",h);//全在墙上
		else  printf("%.3lf\n",H+D-x*2);//一部分在地上,一部分在墙上
	}
	return  0;
}

光速逃,耶!写完了!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章