列表

详情


NC201114. Moon

描述

Let be a sphere with radius and center . Let be points on the surface of . The positions of are fixed while the position of a_0 is a uniform random point on the surface of . Let be if there exists a hemisphere of that contains and otherwise. Calculate the expected value of .

输入描述

The first line contains an integer  denoting the number of points ().
The -th line of the next lines contains three integers denoting the point ().
It is guaranteed that are distinct.

输出描述

Output the answer.
The answer will be considered correct if its absolute or relative error doesn't exceed .

示例1

输入:

3
1 0 0
0 1 0
0 0 1

输出:

0.875000000000

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 155ms, 内存消耗: 7372K, 提交时间: 2020-01-08 15:18:37

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 100011;
const int mod = 1e9 + 7;
typedef double D;
D pi = acos((D)-1.);
typedef long long J;
struct P {
	LL x, y, z;
	void scan() {
		cin >> x >> y >> z;
	}
	void print() const {
		cerr << x << ' ' << y << ' ' << z << endl;
	}
	P operator + (const P & b) const { return P{x + b.x, y + b.y, z + b.z}; }
	P operator - (const P & b) const { return P{x - b.x, y - b.y, z - b.z}; }
	P operator * (const P & b) const { return P{y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x}; }
	J operator % (const P & b) const { return (J)x * b.x + (J)y * b.y + (J)z * b.z; }
	LL sqrlen() const { return x * x + y * y + z * z; }
	D len() const { return sqrt((D)x * x + (D)y * y + (D)z * z); }
	bool operator < (const P & b) const {
		return x < b.x || x == b.x && y < b.y || x == b.x && y == b.y && z < b.z;
	}
	int sgn() const {
		return *this < P{0, 0, 0} ? -1 : P{0, 0, 0} < *this ? 1 : 0;
	}
	bool operator == (const P & b) const { return x == b.x && y == b.y && z == b.z; }
} a[N], b[N], c[N];
int main() {
	int n;
	scanf("%d", &n);
	for(int i(0); i < n; i++) {
		a[i].scan();
	}
	int mxk, mxj, cnt;
	for(int d = 0; d < 2; d++) {
		int nb = 0;
		for(int i(1); i < n; i++) {
			b[nb++] = a[i];
			if(a[0] * a[i] == P{0, 0, 0}) {
				nb--;
			}
		}
		P norm = a[0] * P{1, 0, 0};
		if(norm == P{0, 0, 0}) norm = a[0] * P{0, 1, 0};
		P n1 = a[0] * norm;
		sort(b, b + nb, [&](const P & x, const P & y) {
			LL d1 = x % norm < 0 || x % norm == 0 && x % n1 < 0;
			LL d2 = y % norm < 0 || y % norm == 0 && y % n1 < 0;
			if(d1 == d2) {
				return (x * y % a[0]) > 0 || (x * y % a[0] == 0) && x % a[0] > y % a[0];
			}else return d1 < d2;
		});
		cnt = 0;
		mxj = -1; mxk = -1;
		for(int i(0); i < nb; i++) {
			if(i == 0 || b[i] * b[i - 1] % a[0] != 0) cnt++;
		}
		if(cnt >= 2) {
			for(int i(0); i < nb; i++) {
				LL res = b[i] * b[(i + 1) % nb] % a[0];
				if(res < 0 || res == 0 && (b[i] * a[0]).sgn() != (b[(i + 1) % nb] * a[0]).sgn()) {
					mxj = i;
				}
			}
		}else mxj = 0;
		if(mxj == -1 && d == 0) {
			vector<P> v;
			for(int i(0); i < nb; i++) {
				while(v.size() >= 2u && (v[v.size() - 2] * v.back() % b[i] <= 0)) {
					v.pop_back();
				}
				v.push_back(b[i]);
			}
			int op = 0, ed = (int)v.size();
			for(;;) {
				if(ed - op >= 3 && (v[ed - 2] * v[ed - 1] % v[op] <= 0)) {
					ed--;
					continue;
				}else if(ed - op >= 3 && (v[ed - 1] * v[op] % v[op + 1] <= 0)) {
					op++;
					continue;
				}else break;
			}
			for(int i(0); i < n; i++) if(a[i] == v[op]) {
				swap(a[i], a[0]);
			}
			continue;
		}
		if(mxj == -1) {
			printf("0\n");
			exit(0);
		}
		for(int i(1); i < n; i++) if(a[i] == b[mxj]) { swap(a[i], a[1]); break; }
	}
	P dir = a[0] + a[1];
	int nc = 0;
	for(int i = 0; i < n; i++) {
		if(a[0] * a[1] % a[i] == 0) {
			c[nc++] = a[i];
		}
	}
	if(nc == n) {
		printf("1\n");
		exit(0);
	}
	sort(c,  c+ nc, [&](const P & x, const P & y) {
		int d1 = x.sgn(), d2 = y.sgn();
		if(d1 == d2) {
			return (x * y).sgn() > 0;
		}else return d1 < d2;
	});
	cnt = 0; mxj = -1;
	bool full_hemi = true;
	for(int i(0); i < nc; i++) {
		LL res = (c[i] * c[(i + 1) % nc]).sgn();
		if(res <= 0) {
			mxj = i;
			mxk = (i + 1) % nc;
			full_hemi = false;
			break;
		}
	}
	if(full_hemi) {
		printf("0.5\n");
		exit(0);
	}
	for(int i(0); i < n; i++) {
		if(a[i] == c[mxj]) {
			swap(a[0], a[i]);
			break;
		}
	}
	for(int i(0); i < n; i++) {
		if(a[i] == c[mxk]) {
			swap(a[1], a[i]);
			break;
		}
	}
	//a[0].print();
	//a[1].print();
	if((a[0] * a[1]).sgn() == 0) {
		sort(a + 2, a + n, [&](const P & x, const P & y) {
			return (x * y % a[0]) < 0;
		});
		D ans = 0;
		for(int i(2); i + 1 < n; i++) {
			//a[i].print();
			//a[i + 1].print();
			ans += asin(abs((a[i] * a[0]) % (a[i + 1])) / abs((a[i] * a[0]).len()) / a[i + 1].len());
		}
		printf("%.12f\n", 1 - ans / 2 / pi);
		exit(0);
	}
	for(int i(2); i < n; i++) {
		if(a[0] * a[1] % a[i] == 0) {
			swap(a[i], a[n - 1]);
			n--; i--;
		}
	}
	sort(a + 2, a + n, [&](const P & x, const P & y) {
		return x * y % dir > 0;
	});
	if(a[0] * a[2] % dir > 0) {

	}else {
		swap(a[0], a[1]);
	}
	for(int i(1); i + 1 < n; i++) swap(a[i], a[i + 1]);
	vector<P> vec;
	for(int i(0); i < n; i++) {
		while(vec.size() >= 2u && (vec[vec.size() - 2] * vec.back() % a[i] <= 0)) {
			vec.pop_back();
		}
		vec.push_back(a[i]);
	}
	int nv = vec.size();
	double ans = 0;
	for(int i(1); i + 1 < nv; i++) {
		P x = vec[i];
		P y = vec[(i + 1) % nv];
		P z = vec[0];
		D lx = x.len(), ly = y.len(), lz = z.len();
		D tmp = atan(abs(x * y % z) / (lx * ly * lz + lx * (y % z) + ly * (x % z) + lz * (x % y)));
		if(tmp < 0) tmp += pi;
		ans += tmp * 2;
	}
	printf("%.12f\n", 1 - ans / 4 / pi);
}

C++(clang++11) 解法, 执行用时: 179ms, 内存消耗: 7440K, 提交时间: 2021-04-10 12:02:49

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 100011;
const int mod = 1e9 + 7;
typedef double D;
D pi = acos((D)-1.);
typedef long long J;
struct P {
	LL x, y, z;
	void scan() {
		cin >> x >> y >> z;
	}
	void print() const {
		cerr << x << ' ' << y << ' ' << z << endl;
	}
	P operator + (const P & b) const { return P{x + b.x, y + b.y, z + b.z}; }
	P operator - (const P & b) const { return P{x - b.x, y - b.y, z - b.z}; }
	P operator * (const P & b) const { return P{y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x}; }
	J operator % (const P & b) const { return (J)x * b.x + (J)y * b.y + (J)z * b.z; }
	LL sqrlen() const { return x * x + y * y + z * z; }
	D len() const { return sqrt((D)x * x + (D)y * y + (D)z * z); }
	bool operator < (const P & b) const {
		return x < b.x || x == b.x && y < b.y || x == b.x && y == b.y && z < b.z;
	}
	int sgn() const {
		return *this < P{0, 0, 0} ? -1 : P{0, 0, 0} < *this ? 1 : 0;
	}
	bool operator == (const P & b) const { return x == b.x && y == b.y && z == b.z; }
} a[N], b[N], c[N];
int main() {
	int n;
	scanf("%d", &n);
	for(int i(0); i < n; i++) {
		a[i].scan();
	}
	int mxk, mxj, cnt;
	for(int d = 0; d < 2; d++) {
		int nb = 0;
		for(int i(1); i < n; i++) {
			b[nb++] = a[i];
			if(a[0] * a[i] == P{0, 0, 0}) {
				nb--;
			}
		}
		P norm = a[0] * P{1, 0, 0};
		if(norm == P{0, 0, 0}) norm = a[0] * P{0, 1, 0};
		P n1 = a[0] * norm;
		sort(b, b + nb, [&](const P & x, const P & y) {
			LL d1 = x % norm < 0 || x % norm == 0 && x % n1 < 0;
			LL d2 = y % norm < 0 || y % norm == 0 && y % n1 < 0;
			if(d1 == d2) {
				return (x * y % a[0]) > 0 || (x * y % a[0] == 0) && x % a[0] > y % a[0];
			}else return d1 < d2;
		});
		cnt = 0;
		mxj = -1; mxk = -1;
		for(int i(0); i < nb; i++) {
			if(i == 0 || b[i] * b[i - 1] % a[0] != 0) cnt++;
		}
		if(cnt >= 2) {
			for(int i(0); i < nb; i++) {
				LL res = b[i] * b[(i + 1) % nb] % a[0];
				if(res < 0 || res == 0 && (b[i] * a[0]).sgn() != (b[(i + 1) % nb] * a[0]).sgn()) {
					mxj = i;
				}
			}
		}else mxj = 0;
		if(mxj == -1 && d == 0) {
			vector<P> v;
			for(int i(0); i < nb; i++) {
				while(v.size() >= 2u && (v[v.size() - 2] * v.back() % b[i] <= 0)) {
					v.pop_back();
				}
				v.push_back(b[i]);
			}
			int op = 0, ed = (int)v.size();
			for(;;) {
				if(ed - op >= 3 && (v[ed - 2] * v[ed - 1] % v[op] <= 0)) {
					ed--;
					continue;
				}else if(ed - op >= 3 && (v[ed - 1] * v[op] % v[op + 1] <= 0)) {
					op++;
					continue;
				}else break;
			}
			for(int i(0); i < n; i++) if(a[i] == v[op]) {
				swap(a[i], a[0]);
			}
			continue;
		}
		if(mxj == -1) {
			printf("0\n");
			exit(0);
		}
		for(int i(1); i < n; i++) if(a[i] == b[mxj]) { swap(a[i], a[1]); break; }
	}
	P dir = a[0] + a[1];
	int nc = 0;
	for(int i = 0; i < n; i++) {
		if(a[0] * a[1] % a[i] == 0) {
			c[nc++] = a[i];
		}
	}
	if(nc == n) {
		printf("1\n");
		exit(0);
	}
	sort(c,  c+ nc, [&](const P & x, const P & y) {
		int d1 = x.sgn(), d2 = y.sgn();
		if(d1 == d2) {
			return (x * y).sgn() > 0;
		}else return d1 < d2;
	});
	cnt = 0; mxj = -1;
	bool full_hemi = true;
	for(int i(0); i < nc; i++) {
		LL res = (c[i] * c[(i + 1) % nc]).sgn();
		if(res <= 0) {
			mxj = i;
			mxk = (i + 1) % nc;
			full_hemi = false;
			break;
		}
	}
	if(full_hemi) {
		printf("0.5\n");
		exit(0);
	}
	for(int i(0); i < n; i++) {
		if(a[i] == c[mxj]) {
			swap(a[0], a[i]);
			break;
		}
	}
	for(int i(0); i < n; i++) {
		if(a[i] == c[mxk]) {
			swap(a[1], a[i]);
			break;
		}
	}
	//a[0].print();
	//a[1].print();
	if((a[0] * a[1]).sgn() == 0) {
		sort(a + 2, a + n, [&](const P & x, const P & y) {
			return (x * y % a[0]) < 0;
		});
		D ans = 0;
		for(int i(2); i + 1 < n; i++) {
			//a[i].print();
			//a[i + 1].print();
			ans += asin(abs((a[i] * a[0]) % (a[i + 1])) / abs((a[i] * a[0]).len()) / a[i + 1].len());
		}
		printf("%.10f\n", 1 - ans / 2 / pi);
		exit(0);
	}
	for(int i(2); i < n; i++) {
		if(a[0] * a[1] % a[i] == 0) {
			swap(a[i], a[n - 1]);
			n--; i--;
		}
	}
	sort(a + 2, a + n, [&](const P & x, const P & y) {
		return x * y % dir > 0;
	});
	if(a[0] * a[2] % dir > 0) {

	}else {
		swap(a[0], a[1]);
	}
	for(int i(1); i + 1 < n; i++) swap(a[i], a[i + 1]);
	vector<P> vec;
	for(int i(0); i < n; i++) {
		while(vec.size() >= 2u && (vec[vec.size() - 2] * vec.back() % a[i] <= 0)) {
			vec.pop_back();
		}
		vec.push_back(a[i]);
	}
	int nv = vec.size();
	double ans = 0;
	for(int i(1); i + 1 < nv; i++) {
		P x = vec[i];
		P y = vec[(i + 1) % nv];
		P z = vec[0];
		D lx = x.len(), ly = y.len(), lz = z.len();
		D tmp = atan(abs(x * y % z) / (lx * ly * lz + lx * (y % z) + ly * (x % z) + lz * (x % y)));
		if(tmp < 0) tmp += pi;
		ans += tmp * 2;
	}
	printf("%.9f\n", 1 - ans / 4 / pi);
}

上一题