积分公式
令曲线
y
=
f
(
x
)
y=f(x)
y=f(x)绕
x
x
x轴旋转,形成的旋转体,则其体积和表面积可以计算积分而得(假设体积和表面积一定存在,积分一定存在,这里不讨论数学问题)。
体积公式为:
V
=
∫
π
y
2
d
x
V={\int}{\pi}{y^2}dx
V=∫πy2dx
表面积公式为
S
=
∫
2
π
y
1
+
y
′
2
d
x
S=\int{2\pi}{y}\sqrt{1+{y^{\prime}}^2}dx
S=∫2πy1+y′2dx
剩下的就是推导定积分公式。
##ZOJ3866 Cylinder Candy##
ZOJ3866,一个圆柱体半径为
r
r
rmm,高度为
h
h
hmm,外围包裹着
d
d
dmm厚的涂层,求其表面积和体积。这个题目要精确到
1
0
−
8
10^{-8}
10−8,推不出积分公式就不用做了。
整个部分最关键的就是四个边角的形状,四个边角合在一起恰好是一个圆环的外半侧。所以关键就是求圆环的外半侧的体积以及表面积。
曲线方程为:
y
=
r
+
d
2
−
x
2
,
x
∈
[
−
d
,
d
]
y=r+\sqrt{d^2-x^2},x\in\left[-d,d\right]
y=r+d2−x2,x∈[−d,d]
则,体积积分为:
V
=
π
∫
(
r
2
+
d
2
−
x
2
+
2
r
d
2
−
x
2
)
d
x
=
π
∫
(
r
2
+
d
2
)
d
x
−
π
∫
x
2
d
x
+
2
π
r
∫
d
2
−
x
2
d
x
V=\pi\int(r^2+d^2-x^2+2r\sqrt{d^2-x^2}\;)dx\\=\pi\int(r^2+d^2)dx-\pi\int{x^2}dx+2\pi{r}\int\sqrt{d^2-x^2}dx
V=π∫(r2+d2−x2+2rd2−x2)dx=π∫(r2+d2)dx−π∫x2dx+2πr∫d2−x2dx
第3项稍微麻烦一点,其不定积分为:
∫
d
2
−
x
2
d
x
=
1
2
x
d
2
−
x
2
+
d
2
2
a
r
c
s
i
n
x
d
+
C
\int\sqrt{d^2-x^2}dx=\frac{1}{2}x\sqrt{d^2-x^2}+\frac{d^2}{2}arcsin{\frac{x}{d}}+C
∫d2−x2dx=21xd2−x2+2d2arcsindx+C
表面积公式首先要求
y
y
y的导数:
y
′
=
−
x
d
2
−
x
2
y\prime=-\frac{x}{\sqrt{d^2-x^2}}
y′=−d2−x2x
所以,
1
+
y
′
2
=
d
2
d
2
−
x
2
1+{y\prime}^2=\frac{d^2}{d^2-x^2}
1+y′2=d2−x2d2
表面积的积分为:
S
=
2
π
∫
(
r
+
d
2
−
x
2
)
d
d
2
−
x
2
d
x
=
2
π
r
d
∫
1
d
2
−
x
2
d
x
+
2
π
d
∫
d
x
S=2\pi\int({r+\sqrt{d^2-x^2}})\frac{d}{\sqrt{d^2-x^2}}dx\\=2\pi{rd}\int\frac{1}{\sqrt{d^2-x^2}}dx+2\pi{d}\int{dx}
S=2π∫(r+d2−x2)d2−x2ddx=2πrd∫d2−x21dx+2πd∫dx
第一项就是
a
r
c
s
i
n
x
d
+
C
arcsin\frac{x}{d}+C
arcsindx+C。
所以,体积和表面积全部可以求出原函数的解析式。
然后把其他部分的圆柱体算上即可。
#include <cstdio>
#include <cmath>
double const PI = acos(-1.0);
double const DELTA = 1E-6;
double R,H,D;
double integral(){
return (2.0*D*R*R+4.0*D*D*D/3.0+D*D*R*PI) * PI;
}
double integral2(){
return 4.0*PI*D*D + 2.0*PI*PI*R*D;
}
int main(){
int nofkase;
scanf("%d",&nofkase);
while( nofkase-- ){
scanf("%lf%lf%lf",&R,&H,&D);
double v = integral() + PI * ( R + D ) * ( R + D ) * H;
double s = integral2() + 2.0 * PI * ( R + D ) * H + 2.0 * PI * R * R;
printf("%.12lf %.12lf\n",v,s);
}
return 0;
}
##ZOJ3898 Stean##
ZOJ3898同样是旋转体的表面积和体积。曲线为:
y
=
2
+
c
o
s
x
y=2+cosx
y=2+cosx
不同点在于定积分公式中有一项是得不到解析式的。但是这道题很明显曲线是周期性函数,定积分的周期就是
π
\pi
π,而题目要求在
1
0
−
2
10^{-2}
10−2以内,所以取
ϵ
\epsilon
ϵ为
1
0
−
3
10^{-3}
10−3或
1
0
−
4
10^{-4}
10−4直接使用积分定义去计算。每次计算需要迭代的次数在几万次,应该是没有问题的。
体积积分:
V
=
π
∫
(
2
+
c
o
s
x
)
2
d
x
=
4
π
∫
d
x
+
4
π
∫
c
o
s
x
d
x
+
π
∫
c
o
s
2
x
d
x
V=\pi\int(2+cosx)^2dx\\=4\pi\int{dx}+4\pi\int{cosx}dx\\+\pi\int{cos^2x}dx
V=π∫(2+cosx)2dx=4π∫dx+4π∫cosxdx+π∫cos2xdx
其中第三项为:
∫
c
o
s
2
x
d
x
=
x
2
+
s
i
n
2
x
4
+
C
\int{cos^2x}dx=\frac{x}{2}+\frac{sin2x}{4}+C
∫cos2xdx=2x+4sin2x+C
表面积积分:
S
=
2
π
∫
(
2
+
c
o
s
x
)
1
+
s
i
n
2
x
d
x
=
4
π
∫
1
+
s
i
n
2
x
d
x
+
2
π
∫
1
+
s
i
n
2
x
d
s
i
n
x
S=2\pi\int(2+cosx)\sqrt{1+sin^2x}\;dx\\=4\pi\int\sqrt{1+sin^2x}\;dx\\+2\pi\int\sqrt{1+sin^2x}\;dsinx
S=2π∫(2+cosx)1+sin2xdx=4π∫1+sin2xdx+2π∫1+sin2xdsinx
其中第一项不知道积不积得出来,反正我没有积出来。数学不行,就用计算机的方法算。第二项令
t
=
s
i
n
x
t=sinx
t=sinx,则
∫
1
+
t
2
d
t
=
1
2
t
1
+
t
2
+
1
2
ln
∣
t
+
1
+
t
2
∣
+
C
\int\sqrt{1+t^2}\;dt=\frac{1}{2}t\sqrt{1+t^2}+\frac{1}{2}\ln{\left|{t+\sqrt{1+t^2}}\right|}+C
∫1+t2dt=21t1+t2+21ln∣
∣t+1+t2∣
∣+C
#include <cstdio>
#include <cmath>
double const PI = acos(-1.);
double const EPS = 1E-4;
//计算一个周期
double init1p(){
double ret = 0.0;
for(double x=0.0;x<=0.5*PI;x+=EPS){
double t = sin(x);
ret += sqrt(1.0+t*t);
}
return 8.0*PI*ret*EPS;
}
double const ONEP = init1p();
double v(double z1,double z2){
return 4.0 * PI * ( z2 - z1 )
+ 4.0 * PI * ( sin(z2) - sin(z1) )
+ 0.5 * PI * ( z2 - z1 )
+ 0.25 * PI * ( sin(z2+z2) - sin(z1+z1) );
}
double s(double z1,double z2){
//计算底面积
double y1 = 2.0 + cos(z1);
double ret = PI * y1 * y1;
//计算解析式的积分
double t2 = sin(z2), t1 = sin(z1);
double tt2 = sqrt(1.0+t2*t2), tt1 = sqrt(1.0+t1*t1);
ret += PI * ( t2 * tt2 - t1 * tt1 )
+ PI * ( log(fabs(t2+tt2)) - log(fabs(t1+tt1)) );
//计算周期
int n = (int)(( z2 - z1 ) / PI);
ret += ONEP * (double)n;
//计算积分
double tmp = 0.0;
for(double x=z1+PI*(double)n;x<=z2;x+=EPS){
double t = sin(x);
tmp += sqrt(1.0+t*t);
}
return ret += tmp * 4.0 * PI * EPS;
}
int main(){
int kase;
scanf("%d",&kase);
while(kase--){
double z1,z2;
scanf("%lf%lf",&z1,&z2);
printf("%.5lf %.5lf\n",v(z1,z2),s(z1,z2));
}
return 0;
}