1 /*LA3485:
2 求解积分方程
3 关于这道题的数学模型:
4 给定抛物线长度L,抛物线函数f(x)=a(x-d)(x+d),求解 |a*d*d|的值,a>0,曲线积分函数lf(x)=sqrt(1+f'(x)^2)
5 a越大,|a*d*d|越大,L越长,所以可以二分求解
6
7 辛普森算法解函数f(x)在区间(a,b)上的积分:
8 模板如下:
9 double simpsonF(double a,double b);//返回测试值
10 double simpsonM(double a,double b,eps,double A);//自适应simpson递归
11 //答案是:simpsonM(a,b,eps,simpsonF(a,b));
12 double simpsonF(double a,double b)
13 {
14 double c=a+(b-a)/2;
15 return (F(a)+4*F(c)+F(b))*(b-a)/6;
16 }
17 double simpsonM(double a,double b,double eps,double A)
18 {
19 double c=a+(b-a)/2;
20 double L=simpsonF(a,c),R=simpsonF(c,b);
21 if (fabs(L+R-A)<=15*eps) return L+R+(L+R-A)/15.0;
22 return simpsonM(a,c,eps/2,L)+simpsonM(c,b,eps/2,R);
23 }
24 简要原理分析:细节部分自己以后需要学习!
25 传统求微积分的方法,是手动计算,但是很多难以写出被积函数,这里用计算机帮助计算。
26 任然使用先微分,再求和的方法。微分就是等分区间,去重点函数值,近似成矩形,最终将面积求和。
27 如果直接使用这个方法,越细分,近似程度越高,计算量越大,不细分,精度不够。以前遇到题目,用朴素算法写错了。
28 我们在函数曲线平缓的地方,少细分一些,在陡峭的地方(容易损失精度)多细分。折中的办法满足了时间和精度的要求。
29
30 */
31
32
33 #include<iostream>
34 #include<stdio.h>
35 #include<string.h>
36 #include<algorithm>
37 #include<stdlib.h>
38 #include<math.h>
39 #include<queue>
40 #include<vector>
41 #include<map>
42 #define LL long long
43 using namespace std;
44 double d,l;
45 double F(double k,double x)//k是枚举的系数
46 {
47 k=k/d/d;
48 return sqrt(1+(2*k*(x))*(2*k*(x)));
49 }
50 double simpsonF(double a,double b,double k)
51 {
52 double c=a+(b-a)/2;
53 return (F(a,k)+4*F(c,k)+F(b,k))*(b-a)/6;
54 }
55 double simpsonM(double a,double b,double eps,double A,double k)
56 {
57 double c=a+(b-a)/2;
58 double L=simpsonF(a,c,k),R=simpsonF(c,b,k);
59 if (fabs(L+R-A)<=15*eps) return L+R+(L+R-A)/15.0;
60 return simpsonM(a,c,eps/2,L,k)+simpsonM(c,b,eps/2,R,k);
61 }
62 double Q(double k)
63 {
64 double ans=simpsonM(-d,d,1e-7,simpsonF(-d,d,k),k);
65 return ans-l;
66 }
67 int T,D,H,B,L;
68 int main()
69 {
70 // freopen("out.txt","w",stdout);
71 cin>>T;
72 for(int cas=1;cas<=T;cas++)
73 {
74 cin>>D>>H>>B>>L;
75 d=(B+0.0)/ceil((B+0.0)/D)/2.0;
76 l=(L+0.0)/ceil((B+0.0)/D);
77 double l1=0,r1=H;
78 while(r1-l1>1e-5)
79 {
80 double m=(l1+r1)/2;
81 if (Q(m)>0) r1=m;else l1=m;
82 }
83 if(cas>1) cout<<endl;
84 printf("Case %d:\n",cas);
85 printf("%.2lf\n",H-l1);
86
87 }
88 return 0;
89 }