「一本通 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;
}

光速逃,耶!寫完了!

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