intmain(){ int n, m, q; scanf("%d %d %d", &n, &m, &q); for (int i = 1; i <= n; ++i) { for (int k = 0; k < T; ++k) h[i][k] = 1; for (int j = 1; j <= m; ++j) { int x; scanf("%d", &x); for (int k = 0; k < T; ++k) h[i][k] = min(h[i][k], hashing(x, k)); } } while (q--) { int x, y; scanf("%d %d", &x, &y); int cnt = 0; for (int k = 0; k < T; ++k) cnt += (abs(h[x][k] - h[y][k]) <= 1e-8); printf("%lf\n", 1.0 * cnt / T); } return0; }
usingnamespace std; using db = double; const db eps = 0.15; minstd_rand gen; structPoint { db x, y; int id; };
structNode { Node* ch[4]; Point rep; db x1, x2, y1, y2, diam; };
db dist(db x1, db y1, db x2, db y2){ returnsqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); }
db dist(Point p, db x, db y){ returndist(p.x, p.y, x, y); }
Node* build(db x1, db x2, db y1, db y2, vector<Point> P);
intmain(){ int n, q; scanf("%d %d", &n, &q); vector<Point> P; for (int i = 1; i <= n; ++i) { db x, y; scanf("%lf %lf", &x, &y); P.push_back({x, y, i}); } Node* root = build(0, 1e6, 0, 1e6, P); while (q--) { db qx, qy; scanf("%lf %lf", &qx, &qy); db mind = 1e18; int ans = -1; queue<Node*> A; A.push(root); while (!A.empty()) { Node* cur = A.front(); A.pop(); for (int i = 0; i < 4; ++i) if (cur->ch[i] != nullptr) { db dis = dist(cur->ch[i]->rep, qx, qy); if (dis < mind) { mind = dis; ans = cur->ch[i]->rep.id; } if ((1 + eps) * (dis - cur->ch[i]->diam) < mind) A.push(cur->ch[i]); } } printf("%d\n", ans); } }
voidWSPD(Node* u, Node* v){ if (u == nullptr || v == nullptr) return; if (u == v && u->size == 1) return; if (u->diam() < v->diam()) swap(u, v); if (u->diam() <= eps * dist(u, v)) { wspd.push_back({u, v}); } for (int i = 0; i < 8; ++i) WSPD(u->ch[i], v); return; }
usingnamespace std; constint maxn = 5e4 + 5; using db = double; int n; mt19937 rnd;
structPoint { db coord[3]; int id; Point(int i) { id = i; for (int i = 0; i < 3; ++i) { int x; scanf("%d", &x); coord[i] = x; } } Point () {} };
structNode { int ch[8]; int size; db diam; Point rep; vector<db> l, r; db delta(){ return size < 2 ? 0 : diam; } } t[(int)2e5]; int tot, root;
structEdge { int i, j; db d; }; vector<Edge> E;
intbuild(vector<Point> P, vector<db> l, vector<db> r){ int u = ++tot; // printf("building %d\n", u); t[u].size = P.size(); t[u].rep = P[rnd() % P.size()]; t[u].l = l, t[u].r = r; auto calcDiam = [](vector<db> l, vector<db> r) { db res = 0; for (int i = 0; i < 3; ++i) res += (l[i] - r[i]) * (l[i] - r[i]); returnsqrt(res); }; t[u].diam = calcDiam(l, r); if (P.size() == 1) return u; vector<db> mid(3); vector<Point> Ps[8]; for (int i = 0; i < 3; ++i) mid[i] = (l[i] + r[i]) / 2; for (auto p : P) { int id = 0; for (int i = 0; i < 3; ++i) { if (p.coord[i] > mid[i]) id |= (1 << i); } Ps[id].push_back(p); } for (int id = 0; id < 8; ++id) { vector<db> ll, rr; for (int i = 0; i < 3; ++i) { if ((id >> i) & 1) { ll.push_back(mid[i]); rr.push_back(r[i]); } else { ll.push_back(l[i]); rr.push_back(mid[i]); } } if (!Ps[id].empty()) t[u].ch[id] = build(Ps[id], ll, rr); } return u; }
int fa[maxn]; intfind(int x){return x == fa[x] ? x : fa[x] = find(fa[x]);}
db dist(const Point &a, const Point &b){ db res = 0; for (int i = 0; i < 3; ++i) res += (a.coord[i] - b.coord[i]) * (a.coord[i] - b.coord[i]); returnsqrt(res); }
db dist(int x, int y){ db res = 0; for (int i = 0; i < 3; ++i) { db d = 0; d = max(d, t[x].l[i] - t[y].r[i]); d = max(d, t[y].l[i] - t[x].r[i]); res += d * d; } returnsqrt(res); }
voidWSPD(int x, int y){ // printf("wspd %d %d\n", x, y); if (x == y && t[x].size < 2) { // puts("r1"); return;} if (t[x].delta() < t[y].delta()) swap(x, y); if (t[x].delta() <= 0.5 * dist(x, y)) { E.push_back({t[x].rep.id, t[y].rep.id, dist(t[x].rep, t[y].rep)}); return; } for (int i = 0; i < 8; ++i) if (t[x].ch[i]) WSPD(t[x].ch[i], y); }
intmain(){ // freopen("1.in", "r", stdin); scanf("%d", &n); vector<Point> P; for (int i = 1; i <= n; ++i) { P.push_back(Point(i)); } vector<db> l, r; for (int i = 0; i < 3; ++i) { l.push_back(0); r.push_back((1 << 30)); } root = build(P, l, r); // puts("built"); for (int i = 1; i <= n; ++i) fa[i] = i; WSPD(root, root); sort(E.begin(), E.end(), [](const Edge &a, const Edge &b) {return a.d < b.d;}); int linked = 0; for (auto &e : E) { int u = find(e.i), v = find(e.j); if (u != v) { fa[u] = v; printf("%d %d\n", e.i, e.j); if (++linked == n - 1) break; } } return0; }
随机平移四分树与 Tree Embedding 求解高维 MST (hw14)
Tree embedding:将数据集 P 从 Rd 映射到 T(V,E) 上,其中 P⊆V。用树上的距离来近似欧氏距离
int n, d, m; db s[60005]; int pi[60005], X0[60005][605]; db X[2005][2005], Y0[60005], Y[2005], XTX[2005][2005], XTXI[2005][2005], tmp[2005][2005], XTY[2005], haty[60005]; db w[2005]; default_random_engine eng(1);
intmain(){ scanf("%d %d", &n, &d); m = 1650; uniform_int_distribution<> dis(0, m - 1); int choices[2] = {1, -1}; uniform_int_distribution<> dis2(0, 1); uniform_real_distribution<> dis3(-1, 1); for (int i = 0; i < n; ++i) { pi[i] = dis(eng); s[i] = choices[dis2(eng)]; } for (int i = 0; i < n; ++i) { int l; scanf("%d", &l); while (l--) { int j, v; scanf("%d %d", &j, &v); --j; // X[i][j] = v X[pi[i]][j] += v * s[i]; X0[i][j] = v; // X[pi[i][j]] += S[pi[i]][i] * X[i][j] } int tmpy; scanf("%d", &tmpy); Y0[i] = tmpy; // Y: n * 1 // S: m * n // X: n * d // X = SX: m * d // SY: m * 1 // X^TX: d * d // (X^TX)^{-1}X^TSY: d*d * d*m * m*1 = d * 1 Y[pi[i]] += s[i] * tmpy; for (int k = 0; k < m; ++k) { for (int i = 0; i < d; ++i) { for (int j = 0; j < d; ++j) { XTX[i][j] += X[k][i] * X[k][j]; } } } for (int i = 0; i < d; ++i) XTX[i][i + d] = 1; // gauss for (int i = 0; i < d; ++i) { for (int j = i; j < d; ++j) { if (abs(XTX[j][i]) > 1e-8) { swap(XTX[i], XTX[j]); break; } } for (int j = 0; j < d; ++j) { if (j == i) continue; db r = XTX[j][i] / XTX[i][i]; for (int k = 0; k < 2 * d; ++k) { XTX[j][k] -= r * XTX[i][k]; } } } for (int i = 0; i < d; ++i) { for (int j = 0; j < d; ++j) { XTXI[i][j] = XTX[i][d + j] / XTX[i][i]; } } for (int i = 0; i < d; ++i) { for (int j = 0; j < m; ++j) { XTY[i] += X[j][i] * Y[j]; } } for (int i = 0; i < d; ++i) { for (int j = 0; j < d; ++j) { w[i] += XTXI[i][j] * XTY[j]; } printf("%lf ", w[i]); } return0; }
Principal Component Analysis (hw17) (1/3)
PCA 就是降维找 basis。
近似求 top principal component 的方法:Power Iteration。
椭球的最长轴。A=XTX=QDQT。
任取一个向量 u,只要其不与 Qe1 垂直,那么反复作用 A 后其必然在 Qe1 方向上反复拉伸。