数据结构
线段树
单点修改,区间和
ll tree[maxn << 2];
void build(int l, int r, int v) { memset(tree, v, sizeof(tree)); }
void update(int root, int left, int right, int pos, int k) {
if (pos < left || pos > right)
return;
if (left == right) {
tree[root] += k;
return;
}
int mid = (left + right) >> 1;
update(lson, left, mid, pos, k);
update(rson, mid + 1, right, pos, k);
tree[root] = tree[lson] + tree[rson];
}
ll query(int root, int left, int right, int ql, int qr) {
if (qr < left || ql > right)
return 0;
if (ql <= left && right <= qr)
return tree[root];
int mid = (left + right) >> 1;
return query(lson, left, mid, ql, qr) + query(rson, mid + 1, right, ql, qr);
}
ll qu(int l, int r) { return query(1, 0, maxn, l, r); }
void up(int p, int k) { update(1, 0, maxn, p, k); }
树论
支配树
truct node {
vector<int> e[maxn];
inline void add(int u, int v) { e[u].push_back(v); }
} a, b, c, d;
int dfn[maxn], id[maxn], dfa[maxn], sdom[maxn], idom[maxn], fa[maxn],
mindfn[maxn], cnt;
void dfs(int u) {
dfn[u] = ++cnt;
id[cnt] = u;
for (int i : a.e[u]) {
if (dfn[i]) {
continue;
}
dfa[i] = u;
dfs(i);
}
}
int find(int x) {
if (x == fa[x]) {
return x;
}
int tmp = find(fa[x]);
if (dfn[sdom[mindfn[fa[x]]]] < dfn[sdom[mindfn[x]]]) {
mindfn[x] = mindfn[fa[x]];
}
return fa[x] = tmp;
}
void zp() {
for (int i = cnt; i > 1; i--) {
int u = id[i];
for (int v : b.e[u]) {
if (!dfn[v]) {
continue;
}
find(v);
if (dfn[sdom[mindfn[v]]] < dfn[sdom[u]]) {
sdom[u] = sdom[mindfn[v]];
}
}
c.add(sdom[u], u);
fa[u] = dfa[u];
u = fa[u];
for (int v : c.e[u]) {
find(v);
sdom[mindfn[v]] == u ? idom[v] = u : idom[v] = mindfn[v];
}
}
for (int i = 2; i <= cnt; i++) {
int u = id[i];
if (idom[u] != sdom[u]) {
idom[u] = idom[idom[u]];
}
}
}
void zp_write(int n) {
for (int i = 2; i <= n; i++) {
d.add(idom[i], i);
}
}
数学
快速乘,快速幂
ll qm(ll a, ll b, ll c) {
long long ans = 0, res = a;
while (b) {
if (b & 1)
ans = (ans + res) % c;
res = (res + res) % c;
b >>= 1;
}
return (ll)ans;
}
ll mul(ll a, ll b) { return (ll)(__int128(a) * b % MOD); }
ll qp(ll a, ll b, ll c) {
ll ans = 1, res = a;
while (b) {
if (b & 1)
ans = qm(ans, res, c);
res = qm(res, res, c);
b >>= 1;
}
return ans;
}
素数
//前置:快速乘,快速幂
//保证long long内结果准确
ll prime[7] = {2, 325, 9375, 28178, 450775, 9780504, 1795265022};
bool Miller_Rabin(ll x) {
ll i, j, k;
ll s = 0, t = x - 1;
if (x == 2)
return true;
if (x < 2 || !(x & 1))
return false;
while (!(t & 1)) {
s++;
t >>= 1;
}
for (i = 0; i < 6 && prime[i] < x; ++i) {
ll a = prime[i];
ll b = qp(a, t, x);
for (j = 1; j <= s; ++j) {
k = qm(b, b, x);
if (k == 1 && b != 1 && b != x - 1)
return false;
b = k;
}
if (b != 1)
return false;
}
return true;
}
逆元
ll modInverse(ll a, ll p) { return qp(a, p - 2ll, p); }
计算几何
极角排序
struct Vector {
int x, y;
};
Vector pp[maxn], vc[maxn];
inline double dc(Vector a, Vector b) {
return 1.0 * a.x * b.y - 1.0 * a.y * b.x;
}
inline int xs(Vector a) {
if (a.x >= 0 && a.y > 0)
return 1;
if (a.x < 0 && a.y >= 0)
return 2;
if (a.x <= 0 && a.y < 0)
return 3;
if (a.x > 0 && a.y <= 0)
return 4;
}
bool operator<(const Vector &a, const Vector &b) {
Vector p1 = a;
Vector p2 = b;
int l1, l2;
l1 = xs(p1);
l2 = xs(p2);
return l1 == l2 ? dc(a, b) > 0 ? 1 : 0 : l1 < l2;
}
2019.11.22集合
const int maxn=100010;
namespace Treap{
int num;
struct Node{
int data,key,sz;
int ls,rs;
Node(){};
Node(int data,int key,int sz,int ls=0,int rs=0):
data(data),key(key),sz(sz),ls(ls),rs(rs){};
}T[maxn];
void pushup(int x){
T[x].sz=T[T[x].ls].sz+T[T[x].rs].sz+1;
}
int newnode(int x){
T[++num]=Node(x,rand(),1);
return num;
}
int merge(int x,int y){
if(!x||!y)return x+y;
if(T[x].key<T[y].key){
T[x].rs=merge(T[x].rs,y);
pushup(x);
return x;
}
else{
T[y].ls=merge(x,T[y].ls);
pushup(y);
return y;
}
}
void split(int now,int k,int &x,int &y){
if(!now){x=y=0;return;}
if(T[now].data<=k)x=now,split(T[now].rs,k,T[now].rs,y);
else y=now,split(T[now].ls,k,x,T[now].ls);
pushup(now);
}
int kth(int now,int k){
while(1){
if(k<=T[T[now].ls].sz)now=T[now].ls;
else if(k==T[T[now].ls].sz+1)return now;
else k-=T[T[now].ls].sz+1,now=T[now].rs;
}
}
}
using namespace Treap;
namespace Treap_with_point{
struct node{
node *ch[2];
int data,key,sz,flip;
int siz(int x){
if(ch[x]!=NULL)return ch[x]->sz;
else return 0;
}
void pushdown(){
if(flip){
flip=0;
swap(ch[0],ch[1]);
if(ch[0]!=NULL)ch[0]->flip^=1;
if(ch[1]!=NULL)ch[1]->flip^=1;
}
}
void maintain(){sz=1+siz(0)+siz(1);}
}*root;
typedef pair<node*,node*> droot;
node *merge(node *a,node *b){
if(a==NULL)return b;
if(b==NULL)return a;
a->pushdown();b->pushdown();
if(a->key<b->key){
a->ch[1]=merge(a->ch[1],b);
a->maintain();
return a;
}
else{
b->ch[0]=merge(a,b->ch[0]);
b->maintain();
return b;
}
}
droot split(node *a,int k){
if(a==NULL)return droot(NULL,NULL);
droot ret;
a->pushdown();
if(a->siz(0)>=k){
ret=split(a->ch[0],k);
a->ch[0]=ret.second;
a->maintain();
ret.second=a;
}
else{
ret=split(a->ch[1],k-a->siz(0)-1);
a->ch[1]=ret.first;
a->maintain();
ret.first=a;
}
return ret;
}
void insert(int x){
node *t=new node;
t->data=x;t->key=rand();t->sz=1;
t->flip=0;t->ch[0]=t->ch[1]=NULL;
root=merge(root,t);
}
void output(node *o){
if(!o)return;
o->pushdown();
if(o->ch[0])output(o->ch[0]);
printf("%d ",o->data);
if(o->ch[1])output(o->ch[1]);
}
}
//the Treap without Rotating,written by ndqzhang1111
typedef long long ll;
bool vis[MAXN];
//int prime[MAXN];
vector<int> prime;
int tot;
void get_prime() {
//int tot = 0;
for (int i = 2; i < MAXN; ++i) {
if (!vis[i])
prime.push_back(i);//prime[tot++] = i;
for (int j = 0; j < prime.size(); ++j) {
int d = i * prime[j];
if (d >= MAXN)
break;
vis[d] = true;
if (i % prime[j] == 0)
break;
}
}
}
//rewrite by KI_aq&ndqzhang1111
typedef long long ll;
//typedef int ll;
const int maxn = 4e6 + 10, mod = 1e9 + 7;
//First Step
namespace Seive {
vector<int> p;
bool np[maxn];
int cnt;
void seive() {
np[1] = 0;
for (int i = 2, d; i < maxn; ++i) {
if (!np[i]) {
p.push_back(i);
}
for (auto v : p) {
if ((d = i * v) >= maxn) {
break;
}
np[d] = 1;
if (i % v == 0) break;
}
}
cnt = p.size();
}
}
namespace Useless_Min25 {
using namespace Seive;
const int M = maxn;
ll N;
ll id1[M], id2[M];
ll id(ll n) {
if (n < M)return id1[n];
else return id2[N / n];
}
ll mul(ll a, ll b) {
return a * b % mod;
}
//f(p^k)=p^2k-p^k
ll f(ll p) {
if (p == 1)return 1;
else return (mul(p, p) - p + mod) % mod;
}
//f(p) should be a poly...;
vector<int> p;
ll w[2 * M];
ll m;
ll g1[2 * M], g2[2 * M], gp1[M], gp2[M];
ll g(int p) {return (g2[p] - g1[p] + mod) % mod;}//Sum_of [n/i]
ll h(int y) {return (gp2[y] - gp1[y] + mod) % mod;}//Sum_of [p[i]]
//calc_in_O(1)
void init_g() {
gp1[0] = 2; gp2[0] = 4;
for (int i = 1; i < p.size(); ++i) {
gp1[i] = (gp1[i - 1] + p[i]) % mod;
gp2[i] = (mul(p[i], p[i]) + gp2[i - 1]) % mod;
}
for (ll i = 1; i <= N; i = N / (N / i) + 1) {
w[++m] = N / i;
if (w[m] < M)id1[w[m]] = m;
else id2[N / w[m]] = m;
//sumh(n,p[i]);
g1[m] = w[m] % mod;
g2[m] = (mul(mul(mul(g1[m], g1[m] + 1), g1[m] * 2 + 1), 166666668) - 1) % mod;
g1[m] = (mul(mul(g1[m], (g1[m] + 1)), 500000004) - 1) % mod;
}
////j from 1->|P| calc g(n,j)
//g(n,j)=g(n,j-1)-f(pj)*(g(n/p[j],j-1)-g(p[j],j-1))
for (int i = 0; i < p.size(); ++i) {
ll sqr_pi = 1ll * p[i] * p[i];
for (int j = 1; j <= m && sqr_pi <= w[j]; ++j) {
ll y = id(w[j] / p[i]);
g1[j] = (g1[j] - mul(p[i], (g1[y] - (i - 1 >= 0 ? gp1[i - 1] : 0) + mod)) + mod) % mod;
g2[j] = (g2[j] - mul(mul(p[i], p[i]), (g2[y] - (i - 1 >= 0 ? gp2[i - 1] : 0) + mod)) + mod) % mod;
}
}
}
int tim;
ll S(ll x, int y) {
if (x <= 1 || (y >= 0 && p[y] > x))return 0;
int k = id(x);
//ans = g(n,|p|) - sumf(n,p[i])
ll ret = (g(k) - h(y) + mod) % mod;
//+F*(pe)*(s...+(e>1))
for (int i = y + 1; i < cnt && 1ll * p[i]*p[i] <= x; ++i) {
ll pe = p[i];
for (int e = 1; pe <= x; ++e, pe = 1ll * pe * p[i] ) {
ret = ( 1ll * ret + 1ll * f(pe % mod) * (S(x / pe, i) + (e != 1)) % mod) % mod;
}
}
return ret;
}
ll sum(ll n) {
N = n; m = 0;
init_g();
return (S(N, -1) + f(1)) % mod;
}
ll Query(ll l, ll r) {
return (sum(r) - sum(l - 1) + mod) % mod;
}
}//Written by KI_aq
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <vector>
using namespace std;
struct Point {
double x, y, z;
} p[105];
double dist(Point a, Point b) {
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) +
(a.z - b.z) * (a.z - b.z));
}
double ac(int n) {
double ans = 1e9;
Point tmp;
tmp.x = tmp.y = tmp.z = 0;
;
int s = 1;
double step = 1000;
double esp = 0.0000001;
while (step > esp) {
for (int i = 1; i <= n; i++) {
if (dist(tmp, p[s]) < dist(tmp, p[i]))
s = i;
}
double Dist = dist(tmp, p[s]);
ans = min(ans, Dist);
tmp.x += (p[s].x - tmp.x) / Dist * step;
tmp.y += (p[s].y - tmp.y) / Dist * step;
tmp.z += (p[s].z - tmp.z) / Dist * step;
step *= 0.999;
}
return ans;
}
int main() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%lf %lf %lf", &p[i].x, &p[i].y, &p[i].z);
}
double ans = ac(n);
printf("%.5f\n", ans);
}//minimal ball cover by lucas
ll tree[maxn << 2];
void build(int l, int r, int v) { memset(tree, v, sizeof(tree)); }
void update(int root, int left, int right, int pos, int k) {
if (pos < left || pos > right)
return;
if (left == right) {
tree[root] += k;
return;
}
int mid = (left + right) >> 1;
update(lson, left, mid, pos, k);
update(rson, mid + 1, right, pos, k);
tree[root] = tree[lson] + tree[rson];
}
ll query(int root, int left, int right, int ql, int qr) {
if (qr < left || ql > right)
return 0;
if (ql <= left && right <= qr)
return tree[root];
int mid = (left + right) >> 1;
return query(lson, left, mid, ql, qr) + query(rson, mid + 1, right, ql, qr);
}
ll qu(int l, int r) { return query(1, 0, maxn, l, r); }
void up(int p, int k) { update(1, 0, maxn, p, k); }
//segtree lucas
struct node {
vector<int> e[maxn];
inline void add(int u, int v) { e[u].push_back(v); }
} a, b, c, d;
int dfn[maxn], id[maxn], dfa[maxn], sdom[maxn], idom[maxn], fa[maxn],
mindfn[maxn], cnt;
void dfs(int u) {
dfn[u] = ++cnt;
id[cnt] = u;
for (int i : a.e[u]) {
if (dfn[i]) {
continue;
}
dfa[i] = u;
dfs(i);
}
}
int find(int x) {
if (x == fa[x]) {
return x;
}
int tmp = find(fa[x]);
if (dfn[sdom[mindfn[fa[x]]]] < dfn[sdom[mindfn[x]]]) {
mindfn[x] = mindfn[fa[x]];
}
return fa[x] = tmp;
}
void zp() {
for (int i = cnt; i > 1; i--) {
int u = id[i];
for (int v : b.e[u]) {
if (!dfn[v]) {
continue;
}
find(v);
if (dfn[sdom[mindfn[v]]] < dfn[sdom[u]]) {
sdom[u] = sdom[mindfn[v]];
}
}
c.add(sdom[u], u);
fa[u] = dfa[u];
u = fa[u];
for (int v : c.e[u]) {
find(v);
sdom[mindfn[v]] == u ? idom[v] = u : idom[v] = mindfn[v];
}
}
for (int i = 2; i <= cnt; i++) {
int u = id[i];
if (idom[u] != sdom[u]) {
idom[u] = idom[idom[u]];
}
}
}
void zp_write(int n) {
for (int i = 2; i <= n; i++) {
d.add(idom[i], i);
}
}//zp tree
ll qm(ll a, ll b, ll c) {
long long ans = 0, res = a;
while (b) {
if (b & 1)
ans = (ans + res) % c;
res = (res + res) % c;
b >>= 1;
}
return (ll)ans;
}
ll mul(ll a, ll b) { return (ll)(__int128(a) * b % MOD); }
ll qp(ll a, ll b, ll c) {
ll ans = 1, res = a;
while (b) {
if (b & 1)
ans = qm(ans, res, c);
res = qm(res, res, c);
b >>= 1;
}
return ans;
}
//前置:快速乘,快速幂
//保证long long内结果准确
ll prime[7] = {2, 325, 9375, 28178, 450775, 9780504, 1795265022};
bool Miller_Rabin(ll x) {
ll i, j, k;
ll s = 0, t = x - 1;
if (x == 2)
return true;
if (x < 2 || !(x & 1))
return false;
while (!(t & 1)) {
s++;
t >>= 1;
}
for (i = 0; i < 6 && prime[i] < x; ++i) {
ll a = prime[i];
ll b = qp(a, t, x);
for (j = 1; j <= s; ++j) {
k = qm(b, b, x);
if (k == 1 && b != 1 && b != x - 1)
return false;
b = k;
}
if (b != 1)
return false;
}
return true;
}
ll modInverse(ll a, ll p) { return qp(a, p - 2ll, p); }
struct Vector {
int x, y;
};
Vector pp[maxn], vc[maxn];
inline double dc(Vector a, Vector b) {
return 1.0 * a.x * b.y - 1.0 * a.y * b.x;
}
inline int xs(Vector a) {
if (a.x >= 0 && a.y > 0)
return 1;
if (a.x < 0 && a.y >= 0)
return 2;
if (a.x <= 0 && a.y < 0)
return 3;
if (a.x > 0 && a.y <= 0)
return 4;
}
bool operator<(const Vector &a, const Vector &b) {
Vector p1 = a;
Vector p2 = b;
int l1, l2;
l1 = xs(p1);
l2 = xs(p2);
return l1 == l2 ? dc(a, b) > 0 ? 1 : 0 : l1 < l2;
}//极角排序
const int INF = 0x7fffffff;
const int maxn = 1e5 + 50;
const double INFF = 1.0 * 1e18;
struct MEdge {
int from, to, cap;
double cost;
MEdge(int from, int to, int cap, double cost)
: from(from), to(to), cap(cap), cost(cost) {}
};
struct MCMF { // qdd tql
int n, s, t, flow;
double cost;
vector<MEdge> es;
vector<vector<int>> G;
vector<double> d;
vector<int> p, a; // dis, prev, add
deque<bool> in;
MCMF(int n, int s, int t)
: n(n), s(s), t(t), flow(0), cost(0.0), G(n + 1), p(n + 1), a(n + 1) {}
void add_edge(int u, int v, int cap, double cost) {
G[u].push_back(es.size());
es.emplace_back(u, v, cap, cost);
G[v].push_back(es.size());
es.emplace_back(v, u, 0, -cost);
}
bool spfa() {
d.assign(n + 1, INFF);
in.assign(n + 1, false);
d[s] = 0;
in[s] = 1;
a[s] = INF;
queue<int> q;
q.push(s);
while (!q.empty()) {
int u = q.front();
q.pop();
in[u] = false;
for (int &i : G[u]) {
MEdge &e = es[i];
if (e.cap && d[e.to] > d[u] + e.cost) {
d[e.to] = d[u] + e.cost;
p[e.to] = i;
a[e.to] = min(a[u], e.cap);
if (!in[e.to]) {
q.push(e.to);
in[e.to] = true;
}
}
}
}
return d[t] != INFF;
}
void solve() {
while (spfa()) {
flow += a[t];
cost += a[t] * d[t];
int u = t;
while (u != s) {
es[p[u]].cap -= a[t];
es[p[u] ^ 1].cap += a[t];
u = es[p[u]].from;
}
}
}
};//dinic