[A. Relic Discovery]
签到
#includeint n; int main() { int T; scanf("%d", &T); while (T--) { scanf("%d", &n); int ans = 0; for (int i = 0; i < n; i++) { int a, b; scanf("%d%d", &a, &b); ans += a * b; } printf("%d\n", ans); } return 0; }
[B. Pocket Cube]
判断所有情况,写丑了。
#includeconst int N = 30; int a[N], b[N]; const int n = 24; bool check() { for (int i = 1; i <= 6; i++) { int j = (i - 1) * 4 + 1; int num = b[j]; for (int cnt = 0; cnt < 4; j++, cnt++) if (b[j] != num) return false; } return true; } int main() { //freopen("in.txt", "r", stdin); int T; scanf("%d", &T); while (T--) { for (int i = 1; i <= 24; i++) scanf("%d", a + i); memcpy(b, a, sizeof(a)); if (check()) { puts("YES"); continue; } memcpy(b, a, sizeof(a)); b[5] = a[1]; b[7] = a[3]; b[9] = a[5]; b[11] = a[7]; b[13] = a[9]; b[15] = a[11]; b[3] = a[15]; b[1] = a[13]; if (check()) { puts("YES"); continue; } memcpy(b, a, sizeof(b)); b[1] = a[5]; b[3] = a[7]; b[5] = a[9]; b[7] = a[11]; b[9] = a[13]; b[11] = a[15]; b[15] = a[3]; b[13] = a[1]; if (check()) { puts("YES"); continue; } memcpy(b, a, sizeof(b)); b[6] = a[2]; b[8] = a[4]; b[10] = a[6]; b[12] = a[8]; b[14] = a[10]; b[16] = a[12]; b[4] = a[16]; b[2] = a[14]; if (check()) { puts("YES"); continue; } memcpy(b, a, sizeof(b)); b[4] = a[8]; b[2] = a[6]; b[6] = a[10]; b[8] = a[12]; b[10] = a[14]; b[12] = a[16]; b[14] = a[2]; b[16] = a[4]; if (check()) { puts("YES"); continue; } memcpy(b, a, sizeof(b)); b[3] = a[19]; b[4] = a[20]; b[23] = a[3]; b[24] = a[4]; b[9] = a[24]; b[10] = a[23]; b[20] = a[9]; b[19] = a[10]; if (check()) { puts("YES"); continue; } memcpy(b, a, sizeof(b)); b[3] = a[23]; b[4] = a[24]; b[23] = a[10]; b[24] = a[9]; b[10] = a[19]; b[9] = a[20]; b[19] = a[3]; b[20] = a[4]; if (check()) { puts("YES"); continue; } memcpy(b, a, sizeof(b)); b[1] = a[21]; b[2] = a[22]; b[21] = a[12]; b[22] = a[11]; b[12] = a[17]; b[11] = a[18]; b[17] = a[1]; b[18] = a[2]; if (check()) { puts("YES"); continue; } memcpy(b, a, sizeof(b)); b[1] = a[17]; b[2] = a[18]; b[21] = a[1]; b[22] = a[2]; b[11] = a[22]; b[12] = a[21]; b[18] = a[11]; b[17] = a[12]; if (check()) { puts("YES"); continue; } memcpy(b, a, sizeof(b)); b[5] = a[23]; b[6] = a[21]; b[23] = a[16]; b[21] = a[15]; b[15] = a[20]; b[16] = a[18]; b[20] = a[6]; b[18] = a[5]; if (check()) { puts("YES"); continue; } memcpy(b, a, sizeof(b)); b[5] = a[18]; b[6] = a[20]; b[23] = a[5]; b[21] = a[6]; b[16] = a[23]; b[15] = a[21]; b[20] = a[15]; b[18] = a[16]; if (check()) { puts("YES"); continue; } memcpy(b, a, sizeof(b)); b[7] = a[17]; b[8] = a[19]; b[24] = a[7]; b[22] = a[8]; b[13] = a[22]; b[14] = a[24]; b[19] = a[13]; b[17] = a[14]; if (check()) { puts("YES"); continue; } memcpy(b, a, sizeof(b)); b[7] = a[24]; b[8] = a[22]; b[24] = a[14]; b[22] = a[13]; b[13] = a[19]; b[14] = a[17]; b[19] = a[8]; b[17] = a[7]; if (check()) { puts("YES"); continue; } puts("NO"); } return 0; }
[C. Pocky]
当 $n > d$ 时,$f(n) = \dfrac{\int_{d} ^{n} f(x)dx}{n} + 1$
当 $n \leq d$ 时,$f(n) = 0$
解得 $f(n) = ln(\dfrac{n}{d}) + 1$
#includeconst double eps = 1e-10; int dcmp(double x) { if (fabs(x) < eps) return 0; return x < 0 ? -1 : 1; } int main() { int T; scanf("%d", &T); while (T--) { double a, b; scanf("%lf%lf", &a, &b); if (dcmp(a - b) <= 0) { puts("0.000000"); continue; } double ans = log(a) - log(b) + 1.0; printf("%.6f\n", ans); } return 0; }
[D. Lucky Coins]
每种硬币都是独立的。那么求出第 $i$ 种硬币在第 $j$ 轮之前都被拿掉的概率 $die[i][j] = (1 - p_{i} ^ j)^{cnt_i}$。$alive[i][j] = 1 - die[i][j]$ 表示第 $i$ 种硬币在第 $j$ 轮还存活的概率。
对于第 $i$ 种硬币的答案就是 $\sum_{step} (alive[i][step] - alive[i][step + 1]) * \prod_{j!=i}die[j][step]$。
#includeconst int N = 15; const int step = 105; double qp(double a, int n) { double ans = 1; while (n) { if (n & 1) ans *= a; a *= a; n >>= 1; } return ans; } double alive[N][step], die[N][step], p[N]; int cnt[N], n; void init(int index) { double pp = p[index]; for (int i = 1; i < step; i++) { die[index][i] = qp(1 - pp, cnt[index]); alive[index][i] = 1 - die[index][i]; pp *= p[index]; } } double solve(int index) { double ans = 0; for (int i = 1; i < step - 1; i++) { double temp = alive[index][i] - alive[index][i + 1]; for (int j = 1; j <= n; j++) { if (j == index) continue; temp *= die[j][i]; } ans += temp; } return ans; } int main() { int T; scanf("%d", &T); while (T--) { scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%d%lf", cnt + i, p + i); init(i); } if (n == 1) { puts("1.000000"); continue; } for (int i = 1; i <= n; i++) printf("%.6f%c", solve(i), " \n"[i == n]); } return 0; }
[G. Coding Contest]
求出最小的崩溃概率,即求最大的未崩溃概率。
转化成二分图。人多于食物的为 $X$,人少于食物的为 $Y$。
概率取对数,跑费用流即可。
#includeconst int N = 500 + 7; const int M = 2e4 + 7; const double inf = 1e12; const int INF = 0x3f3f3f3f; struct E { int v, ne, f; double c; } e[M]; int head[N], cnt; double dis[N]; int path[N], n, m; bool inq[N]; inline void add(int u, int v, int f, double c) { e[cnt].v = v; e[cnt].f = f; e[cnt].c = c; e[cnt].ne = head[u]; head[u] = cnt++; e[cnt].v = u; e[cnt].f = 0; e[cnt].c = -c; e[cnt].ne = head[v]; head[v] = cnt++; } const double eps = 1e-8; int dcmp(double x) { if (fabs(x) < eps) return 0; return x < 0 ? -1 : 1; } bool spfa(int s, int t) { for (int i = 0; i <= t; i++) dis[i] = inf, inq[i] = 0, path[i] = -1; dis[s] = 0; inq[s] = 1; std::queue<int> que; que.push(s); while (!que.empty()) { int u = que.front(); que.pop(); inq[u] = 0; for (int i = head[u]; ~i; i = e[i].ne) { int v = e[i].v; double c = e[i].c; if (e[i].f && dcmp(dis[v] - dis[u] - c) > 0) { dis[v] = dis[u] + c; path[v] = i; if (!inq[v]) { inq[v] = 1; que.push(v); } } } } return dis[t] != inf; } double mcf(int s, int t) { double ans = 0; while (spfa(s, t)) { int x = INF; for (int i = path[t]; ~i; i = path[e[i ^ 1].v]) x = std::min(x, e[i].f); ans += dis[t] * x; for (int i = path[t]; ~i; i = path[e[i ^ 1].v]) e[i].f -= x, e[i ^ 1].f += x; } return ans; } int main() { //freopen("in.txt", "r", stdin); int T; scanf("%d", &T); while (T--) { memset(head, -1, sizeof(head)); cnt = 0; scanf("%d%d", &n, &m); int s = 0, t = n + 1; for (int i = 1; i <= n; i++) { int S, B; scanf("%d%d", &S ,&B); if (S > B) add(s, i, S - B, 0); else if(S0); } for (int i = 1; i <= m; i++) { int u, v, c; double p; scanf("%d%d%d%lf", &u, &v, &c, &p); add(u, v, 1, 0); if (c > 1) add(u, v, c - 1, -log(1.0 - p)); } printf("%.2f\n", 1.0 - exp(-mcf(s, t))); } return 0; }
[K. Finding Hotels]
KD-tree查最近点对。用最小花费和估价函数剪枝。
#include#define ll long long #define pii pair #define fi first #define se second namespace IO { char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh = ' '; int p, p3 = -1; void read() {} void print() {} inline int getc() { return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; } inline void flush() { fwrite(buf2, 1, p3 + 1, stdout), p3 = -1; } template inline void read(T &x, T2 &... oth) { T f = 1; x = 0; char ch = getc(); while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getc(); } while (isdigit(ch)) { x = x * 10 + ch - 48; ch = getc(); } x *= f; read(oth...); } template inline void print(T x, T2... oth) { if (p3 > 1 << 20) flush(); if (x < 0) buf2[++p3] = 45, x = -x; do { a[++p] = x % 10 + 48; } while (x /= 10); do { buf2[++p3] = a[p]; } while (--p); buf2[++p3] = hh; print(oth...); } } // using namespace IO #define read IO::read #define print IO::print #define flush IO::flush template<class T> inline void checkmax(T &a, T b) { if (a < b) a = b; } template<class T> inline void checkmin(T &a, T b) { if (a > b) a = b; } ll sqr(int x) { return 1LL * x * x; } const int N = 2e5 + 7; const ll inf = 0x3f3f3f3f3f3f3f3f; const int INF = 0x3f3f3f3f; int n, m, D, root; std::pii ans; struct Node { int lp, rp, id; int d[3], mx[3], mn[3]; inline bool operator < (const Node &rhs) const { return d[D] < rhs.d[D]; } void clear() { lp = rp = id = 0; for (int i = 0; i < 3; i++) d[i] = mx[i] = mn[i] = 0; } } tree[N], qu, in[N]; struct Kd { #define lp tree[p].lp #define rp tree[p].rp inline void pushup(int p, int s) { for (int i = 0; i < 3; i++) checkmax(tree[p].mx[i], tree[s].mx[i]), checkmin(tree[p].mn[i], tree[s].mn[i]); } inline void pushup(int p) { for (int i = 0; i < 3; i++) tree[p].mx[i] = tree[p].mn[i] = tree[p].d[i]; if (lp) pushup(p, lp); if (rp) pushup(p, rp); } int build(int l, int r, int d) { D = d; int mid = l + r >> 1, p = mid; std::nth_element(tree + l, tree + mid, tree + r + 1); if (l != mid) lp = build(l, mid - 1, (d + 1) % 3); else lp = 0; if (r != mid) rp = build(mid + 1, r, (d + 1) % 3); else rp = 0; pushup(p); return p; } ll gu(int p) { if (qu.d[2] < tree[p].mn[2]) return inf + 1; ll ret = 0; for (int i = 0; i < 2; i++) { if (qu.d[i] > tree[p].mx[i]) ret += sqr(qu.d[i] - tree[p].mx[i]); if (qu.d[i] < tree[p].mn[i]) ret += sqr(qu.d[i] - tree[p].mn[i]); } return ret; } ll dis(int p) { if (qu.d[2] < tree[p].d[2]) return inf + 1; ll ret = 0; for (int i = 0; i < 2; i++) ret += sqr(qu.d[i] - tree[p].d[i]); return ret; } void query(int p) { if (!p) return; ll cur = dis(p); if (cur < ans.fi || (cur == ans.fi && tree[p].id < ans.se)) ans.fi = cur, ans.se = tree[p].id; ll dl = 0, dr = 0; if (lp) dl = gu(lp); if (rp) dr = gu(rp); if (dl < dr) { if (dl <= ans.fi && lp) query(lp); if (dr <= ans.fi && rp) query(rp); } else { if (dr <= ans.fi && rp) query(rp); if (dl <= ans.fi && lp) query(lp); } } } kd; int main() { freopen("in.txt", "r", stdin); int T; read(T); for ( ; T--; ) { read(n, m); for (int i = 1; i <= n; i++) { tree[i].clear(); tree[i].id = i; for (int j = 0; j < 3; j++) read(tree[i].d[j]); in[i] = tree[i]; } root = kd.build(1, n, 1); for (int i = 1; i <= m; i++) { ans.fi = inf, ans.se = 0; for (int j = 0; j < 3; j++) read(qu.d[j]); kd.query(root); printf("%d %d %d\n", in[ans.se].d[0], in[ans.se].d[1], in[ans.se].d[2]); } } return 0; }