zoj 3898 Stean 高等数学 数值积分

题目

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3898

题目来源:ZOJ 月赛 给跪

简要题意:一个桶底和盖的 Z 坐标为Z1,Z2,桶的半径 R=2+cosZ ,求体积和内表面积。

数据范围: 1T300;|Z1|,|Z2|1000.00

题解

这是一道纯高数题。

首先对于体积的话非常好搞,学过微积分可以直接算出来:

V=Z2Z1π(2+cosz)2dz=πZ2Z1(4+4cosz+cos2z) dz=πZ2Z1(4+4cosz+1+cos2z2) dz=π(9z2+4sinz+sin2z4)Z2Z1

然后表面积的话首先有底为 πZ21

然后就剩下要求侧面积了。

一个错误的想法是去求 Z2Z12π(2+cosz) dz ,因为就算分得很小点也没法代替弧长。

实际上我们求的时候需要再乘上弧长,弧长的微元有 ds=1+y2 dx

于是有我们要求的就是:

S=πZ21+2πZ2Z1(2+cosz)1+sin2z dz

后边那坨积分算出来的东西是个椭圆积分,没法用初等函数表示。

然后就需要使用复合 Simpson 来搞。

不会的可以参考:http://blog.csdn.net/xc19952007/article/details/48472033

实现

直接用复合 Simpson 精度实际上是不够的。

考虑三角函数的特殊性我们可以知道 2π 区间内的积分值是相同的。

这样我们就可以处理一段 [0,2π] 的和砍掉一堆周期之后剩下的长度小于 2π 的一段就行了。

曾经有过一个错误的想法是砍成一堆 π ,由于想着是个偶函数就这么干了。

实际上由于它的积分是个奇函数,而且并非三角函数,所以能确定的周期只有 2π π 作为周期是错的。

这个利用 z+2π 的代入很好证明。

代码

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>

#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
#define getmid(l,r) ((l) + ((r) - (l)) / 2)
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
LL powmod(LL a,LL b, LL MOD) {LL res=1;a%=MOD;for(;b;b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;}
// head
const double PI = acos(-1.0);
const double EPS = 1e-5;

double calV(double l, double r) {
    return (PI*9*(r-l)/2+4*PI*(sin(r)-sin(l))+PI*(sin(r) * cos(r) - sin(l) * cos(l)) / 2);
}

inline double getR(double x) {
    return 2+cos(x);
}
inline double sqr(double x) {
    return x*x;
}
inline double f(double x) {
    return 2*PI*sqrt(1+sqr(sin(x)))*getR(x);
}

inline double getAppr(double fl, double fm, double fr, double l, double r) {
    return (fl+4*fm+fr)*(r-l)/6.0;
}

double Simpson(double l, double r, double fl, double fr) {
    double m = (l+r)/2, lm = (l+m)/2, rm = (r+m)/2;
    double fm = f(m), flm = f(lm), frm = f(rm);
    double vlr = getAppr(fl, fm, fr, l, r);
    double vlm = getAppr(fl, flm, fm, l, m);
    double vrm = getAppr(fm, frm, fr, m, r);
    return fabs(vlr-vlm-vrm) < EPS ? vlr : Simpson(l, m, fl, fm)+Simpson(m, r, fm, fr);
}

double calS(double l, double r) {
    double PIS = Simpson(0, 2*PI, f(0), f(2*PI));
    double p = floor((r-l)/PI/2);
    return PIS*p + Simpson(l+p*PI*2, r, f(l+p*PI*2), f(r));
}

int main() {
    int t;
    double l, r;
    scanf("%d", &t);
    while (t--) {
        scanf("%lf%lf",&l, &r);
        printf("%.2f %.2f\n", calV(l, r), PI*sqr(getR(l))+calS(l, r));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值