题目大意
题目描述
给定二维平面上的一个标准椭圆方程:
x 2 a 2 + y 2 b 2 = 1 \frac{x^2}{a^2} + \frac{y^2}{b^2} = 1
a 2 x 2 + b 2 y 2 = 1
其中 a a a 和 b b b 是正实数,分别代表椭圆的半轴。
同时给定平面上的一条直线方程:
y = k x + c y = kx + c
y = k x + c
已知该直线一定会将椭圆分割成两个区域,要求计算并输出这两个区域中面积较大 的那一部分的面积。
输入格式
第一行包含两个整数 a a a 和 b b b (1 ≤ a , b ≤ 1 0 3 1 \le a,b \le 10^3 1 ≤ a , b ≤ 1 0 3 ),表示椭圆的两个半轴长。
第二行包含两个整数 k k k 和 c c c (∣ k ∣ , ∣ c ∣ ≤ 1 0 3 |k|,|c| \le 10^3 ∣ k ∣ , ∣ c ∣ ≤ 1 0 3 ),定义了直线 y = k x + c y = kx + c y = k x + c 。
数据保证直线必定与椭圆相交于两个不同的点。
输出格式
输出一个浮点数,表示椭圆中面积较大那一部分的面积。
你的答案与标准答案的绝对误差或相对误差不超过 1 0 − 6 10^{-6} 1 0 − 6 即被视为正确。
样例
输入
输出
样例解释
在样例中,给定椭圆方程为 x 2 2 2 + y 2 3 2 = 1 \frac{x^2}{2^2} + \frac{y^2}{3^2} = 1 2 2 x 2 + 3 2 y 2 = 1 ,即 x 2 4 + y 2 9 = 1 \frac{x^2}{4} + \frac{y^2}{9} = 1 4 x 2 + 9 y 2 = 1 。
给定直线方程为 y = x + 1 y = x + 1 y = x + 1 。
整个椭圆的面积为 π × a × b = 6 π ≈ 18.8495559 \pi \times a \times b = 6\pi \approx 18.8495559 π × a × b = 6 π ≈ 1 8 . 8 4 9 5 5 5 9 。
直线 y = x + 1 y = x + 1 y = x + 1 穿过该椭圆将其分成两部分,经过计算,这两部分中面积较大的区域面积约为 12.709803500 12.709803500 1 2 . 7 0 9 8 0 3 5 0 0 。
思路讲解
椭圆方程 x 2 a 2 + y 2 b 2 = 1 \frac{x^2}{a^2} + \frac{y^2}{b^2} = 1 a 2 x 2 + b 2 y 2 = 1 ,做代换 u = x a , v = y b u = \frac{x}{a},\; v = \frac{y}{b} u = a x , v = b y ,椭圆变成 u 2 + v 2 = 1 u^2 + v^2 = 1 u 2 + v 2 = 1 (单位圆)。
直线 y = k x + c y = kx + c y = k x + c 变成 b v = k a ⋅ u + c bv = ka \cdot u + c b v = k a ⋅ u + c ,即 v = k a b u + c b v = \frac{ka}{b}\,u + \frac{c}{b} v = b k a u + b c 。
面积缩放关系 :这个变换的雅可比行列式是 a b ab a b ,所以在 ( u , v ) (u,v) ( u , v ) 平面上算出的面积,乘以 a b ab a b 就是椭圆上的面积 。
具体而言,雅克比行列式是:
u = x a , v = y b u = \frac{x}{a}, \quad v = \frac{y}{b}
u = a x , v = b y
反过来就是 x = a u , y = b v x = au,\; y = bv x = a u , y = b v 。雅可比矩阵是把所有偏导数摆成矩阵:
J = ( ∂ x ∂ u ∂ x ∂ v ∂ y ∂ u ∂ y ∂ v ) = ( a 0 0 b ) J = \begin{pmatrix} \frac{\partial x}{\partial u} & \frac{\partial x}{\partial v} \\ \frac{\partial y}{\partial u} & \frac{\partial y}{\partial v} \end{pmatrix} = \begin{pmatrix} a & 0 \\ 0 & b \end{pmatrix}
J = ( ∂ u ∂ x ∂ u ∂ y ∂ v ∂ x ∂ v ∂ y ) = ( a 0 0 b )
雅可比行列式 = det ( J ) = a b − 0 = a b \det(J) = ab - 0 = ab det ( J ) = a b − 0 = a b 。
这意味着:( u , v ) (u,v) ( u , v ) 平面上任何一块面积为 S S S 的区域,对应回 ( x , y ) (x,y) ( x , y ) 平面上面积为 a b ⋅ S ab \cdot S a b ⋅ S 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 void Solve () { ll a0, b0, k0, c0; cin >> a0 >> b0 >> k0 >> c0; DB k1 = (DB) (k0 * a0) / b0; DB c1 = c0 / DB (b0); DB dis = distancePL (Point (0 , 0 ), Line (k1, c1)); cout << fsp (10 ); if (dis == 0 ) { DB area = pi * a0 * b0; area /= 2 ; cout << area << "\n" ; return ; } DB xian = 2 * sqrt (1 - dis * dis); DB angle = 2 * acos (dis / 1 ); DB shan = (angle / (2 * pi)) * pi; DB area = shan - 0.5 * dis * xian; area *= a0; area *= b0; area = max (area, pi * a0 * b0 - area); cout << area << "\n" ; }
AC代码
AC
https://codeforces.com/gym/106139/submission/367303278
源代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 #include <bits/stdc++.h> #define all(vec) vec.begin(),vec.end() #define lson(o) (o<<1) #define rson(o) (o<<1|1) #define SZ(a) ((long long) a.size()) #define debug(var) cerr << #var <<" = [" <<var<<"]" <<"\n" ; #define debug1d(a) \ cerr << #a << " = [" ; \ for (int i = 0; i < (int)(a).size(); i++) \ cerr << (i ? ", " : "" ) << a[i]; \ cerr << "]\n" ; #define debug2d(a) \ cerr << #a << " = [\n" ; \ for (int i = 0; i < (int)(a).size(); i++) \ { \ cerr << " [" ; \ for (int j = 0; j < (int)(a[i]).size(); j++) \ cerr << (j ? ", " : "" ) << a[i][j]; \ cerr << "]\n" ; \ } \ cerr << "]\n" ; #define cend cerr<<"\n-----------\n" #define fsp(x) fixed<<setprecision(x) using namespace std;using ll = long long ;using ull = unsigned long long ;using DB = long double ;using i128 = __int128;using CD = complex<double >;const double pi = acos (-1.0 );ll lT, testcase; void Solve () { ll a0, b0, k0, c0; cin >> a0 >> b0 >> k0 >> c0; DB k1 = (DB) (k0 * a0) / b0; DB c1 = c0 / DB (b0); DB dis; if (k1 == 0 ) { dis = abs (c1); } else { if (c1 == 0 ) { dis = 0 ; } else { dis = ((c1 * c1) / k1) * (1.0 / sqrt (c1 * c1 + (c1 * c1) / (k1 * k1))); dis = abs (dis); } } cout << fsp (10 ); if (dis == 0 ) { DB area = pi * a0 * b0; area /= 2 ; cout << area << "\n" ; return ; } DB xian = 2 * sqrt (1 - dis * dis); DB angle = 2 * acos (dis / 1 ); DB shan = (angle / (2 * pi)) * pi; DB area = shan - 0.5 * dis * xian; #ifdef LOCAL debug (area); #endif area *= a0; area *= b0; area = max (area, pi * a0 * b0 - area); #ifdef LOCAL debug (area); debug (shan); debug (xian); debug (dis); #endif cout << area << "\n" ; } signed main () { ios::sync_with_stdio (false ); cin.tie (nullptr ); cout.tie (nullptr ); #ifdef LOCAL cout.setf (ios::unitbuf); #endif Solve (); return 0 ; }
心路历程(WA,TLE,MLE……)
这个形式一定要化简到 v=u。。。什么的形式