例①:Ellipse HDU - 1724:
Math is important!! Many students failed in 2+2’s mathematical test, so let’s AC this problem to mourn for our lost youth…
Look this sample picture:
A ellipses in the plane and center in point O. the L,R lines will be vertical through the X-axis. The problem is calculating the blue intersection area. But calculating the intersection area is dull, so I have turn to you, a talent of programmer. Your task is tell me the result of calculations.(defined PI=3.14159265 , The area of an ellipse A=PIab )
Input
Input may contain multiple test cases. The first line is a positive integer N, denoting the number of test cases below. One case One line. The line will consist of a pair of integers a and b, denoting the ellipse equation , A pair of integers l and r, mean the L is (l, 0) and R is (r, 0). (-a <= l <= r <= a).
Output
For each case, output one line containing a float, the area of the intersection, accurate to three decimals after the decimal point.
Sample Input
2
2 1 -2 2
2 1 0 2
Sample Output
6.283
3.142
将 x 轴上方的 y 化为 x 的函数,积分出来之后乘以2即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<deque>
#include<map>
#include<vector>
#include<cmath>
#define ll long long
#define llu unsigned ll
using namespace std;
const double eps = 1e-5;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const int maxn=100010;
const int mod=1e9+7;
double a,b,l,r;
double f(double x)
{
return b*sqrt(1.0-(x*x)/(a*a));
}
double s(double a,double b)
{
double c=(a+b)/2;
return (b-a)*(f(a)+f(b)+f(c)*4.0)/6.0;
}
double area(double a,double b,double eps,double ans)
{
double c=(a+b)/2;
double l=s(a,c),r=s(c,b);
if(abs(l+r-ans)<=15*eps) return l+r+(l+r-ans)/15.0;
else return area(a,c,eps/2,l)+area(c,b,eps/2,r);
}
int main(void)
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%lf%lf%lf%lf",&a,&b,&l,&r);
printf("%.3f\n",2.0*area(l,r,eps,s(l,r)));
}
return 0;
}
例②:P4525 【模板】自适应辛普森法1:
题目描述
计算积分
结果保留至小数点后6位。
数据保证计算过程中分母不为0且积分能够收敛。
输入格式
一行,包含6个实数a,b,c,d,L,R
输出格式
一行,积分值,保留至小数点后6位。
输入输出样例
输入 #1 复制
1 2 3 4 5 6
输出 #1 复制
2.732937
说明/提示
a,b,c,d∈[-10,10]
-100≤L<R≤100 且 R-L≥1
其实这个积分挺简单的,求出原函数来就好啦,但是为了练习辛普森,我就用辛普森来写了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<deque>
#include<map>
#include<vector>
#include<cmath>
#define ll long long
#define llu unsigned ll
using namespace std;
const double eps = 1e-8;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const int maxn=100010;
const int mod=1e9+7;
double a,b,c,d,l,r;
double f(double x)
{
return (c*x+d)/(a*x+b);
}
double s(double a,double b)
{
double c=(a+b)/2;
return (b-a)*(f(a)+f(b)+f(c)*4.0)/6.0;
}
double area(double a,double b,double eps,double ans)
{
double c=(a+b)/2;
double l=s(a,c),r=s(c,b);
if(abs(l+r-ans)<=15*eps) return l+r+(l+r-ans)/15.0;
else return area(a,c,eps/2,l)+area(c,b,eps/2,r);
}
int main(void)
{
scanf("%lf%lf%lf%lf%lf%lf",&a,&b,&c,&d,&l,&r);
printf("%.6f\n",area(l,r,eps,s(l,r)));
return 0;
}
例③:P4526 【模板】自适应辛普森法2:
题目描述
计算积分
保留至小数点后5位。若积分发散,请输出"orz"。
输入格式
一行,包含一个实数,为a的值
输出格式
一行,积分值或orz
输入输出样例
输入 #1 复制
2.33
输出 #1 复制
1.51068
说明/提示
a<=50
请注意时空限制。
很容易就能看出a<0时,当x趋近于0的时候是发散的。
所以我们只计算a≥0的积分值,当a≥0时,被积函数很快趋近与0,所以随便选一个不很大且不很小的正整数作为积分上限即可。
因为 x 在分母上,所以不能为0,我们可以从一个很小的但是不为0的值开始积分。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<deque>
#include<map>
#include<vector>
#include<cmath>
#define ll long long
#define llu unsigned ll
using namespace std;
const double eps = 1e-7;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const int maxn=100010;
const int mod=1e9+7;
double a;
double f(double x)
{
return pow(x,a/x-x);
}
double s(double a,double b)
{
double c=(a+b)/2;
return (b-a)*(f(a)+f(b)+f(c)*4.0)/6.0;
}
double area(double a,double b,double eps,double ans)
{
double c=(a+b)/2;
double l=s(a,c),r=s(c,b);
if(abs(l+r-ans)<=15*eps) return l+r+(l+r-ans)/15.0;
else return area(a,c,eps/2,l)+area(c,b,eps/2,r);
}
int main(void)
{
scanf("%lf",&a);
if(a<0) printf("orz\n");
else printf("%.5f\n",area(eps/1000,23,eps,s(eps/1000,23)));
return 0;
}