1.题目链接。题目的意思很简单,就是求阴影部分的面积,图形是一个椭圆。
2.思路:这个做法当然有很多种了,最暴力的就是直接积分了,用一下三角换元也是很简单的就搞定了。其实化简到最后可能涉及到反三角函数的化简,这个就量力而行了呗,有能力继续的,就可以继续(其实没必要,也不是做数学题),搞不明白反三角怎么化简得,直接就写公式上去。第二种方法就是Simpson积分法了,自适应得Simpson积分很简单得就解决了这个问题。第三种,也是我百思不得为什么WA了得一种,就是使用仿射变换,我们知道,可以把椭圆通过坐标系得放缩变成一个圆,然后在圆里面把面积求出来,因为这个坐标变换是按照比例变换得,所以面积也是成比例的,比如:我们做这样的变换:x0=x,y0=(a/b)y,反解出x,y带入就可以的到一个关于x0,y0的方程,这是一个圆,半径就是a.那么我们知道两条直线在这个变换下还是不变的,所以区间还是[l,r],那么在这个圆里面的面积和之前面积的关系就是:s0=(a/b)s.我们只要把s0求出来就行了,s0很简单求了,分成三个部分,左右的三角形,加上中间的扇形,中间的圆心角用余弦定理求出来,面积搞定,再转代回去,就可以得到s了。emmmmm,可是莫名其妙的WA了,也不知怎么回事,在WA了五六发之后,我一怒之下撸了个Simpson A了它。代码如下:
//#include"stdafx.h"
//#include<iostream>
//#include<cmath>
//using namespace std;
//#pragma warning(disable:4996)
//int main()
//{
// int T;
// scanf("%d", &T);
// int a, b, l, r;
// while (T--)
// {
// scanf("%d%d%d%d", &a, &b, &l, &r);
// if (l == r)
// {
// cout << "0.00" << endl;
// continue;
//
// }
// double ly = sqrt(pow(a, 2) - pow(l, 2));
// double ry = sqrt(pow(a, 2) - pow(r, 2));
// double dis = sqrt(pow(l - r, 2) + pow(ly - ry, 2));
// double csita = (2 * pow(a, 2) - pow(dis, 2))*1.0 / (2 * a*a);
// double sita = acos(csita);
// double s1 = a * a*sita / 2;
// double s2 = abs(l)*sqrt(pow(a, 2) - pow(l, 2)) / 2;
// double s3 = abs(r)*sqrt(pow(a, 2) - pow(r, 2)) / 2;
// double s = s1 + s2 + s3;
// s *= 2;
// s = s * (b*1.0 / a);
// printf("%.4lf\n", s);
// }
//}
#include"stdafx.h"
#include<iostream>
using namespace std;
const double eps = 1e-9;
#pragma warning(disable:4996)
//f函数
double a, b, l, r;
double f(double x)
{
return sqrt((1 - x * x / (a*a))*(b*b));
}
//Simpson公式
double simpson(double l, double r)
{
return (f(l) + 4 * f((l + r) / 2) + f(r))*(r - l) / 6;
}
double simpson(double l, double r,double all,double eps)
{
double mid = (l + r) / 2;
double L = simpson(l, mid);
double R = simpson(mid, r);
if (fabs(L + R - all) <= 15 * eps)
return L + R + (L + R - all) / 15;
return simpson(l, mid, L, eps / 2) + simpson(mid, r, R, eps / 2);
}
double simpson(double l, double r, double eps)
{
return simpson(l, r, simpson(l, r), eps);
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
scanf("%lf%lf%lf%lf", &a, &b, &l, &r);
printf("%.3lf\n", 2*simpson(l, r,1e-4));
}
return 0;
}
上边是我用仿射变换的代码,等我找到BUG了,再把它放出来。