2020 Multi-University Training Contest 1 部分題解
阿新 • • 發佈:2020-07-22
目錄
Distinct Sub-palindromes
簽到,發現長度 \(>3\) 只能形如 \(abcabcabc...\),算下 \(3\) 的答案即可。
Code
int main() { ans[1] = 26, ans[2] = 26 * 26, ans[3] = 26 * 25 * 24 + 26 * 25 + 26 * 25 + 26 * 25 + 26; for (ri tt = read(); tt; --tt) { int n = read(); if (n <= 3) cout << ans[n] << '\n'; else cout << 26 * 25 * 24 << '\n'; } return 0; }
Fibonacci Sum
等比數列求和,要特判 \(1\)。
場上過了的賽後被卡常了...卡了一波終於過了。
Code
int main() { A = mul(iv2, add(1, bas)), B = mul(iv2, dec(1, bas)); init(100000); for (ri tt = read(), tp = mul(Inv(A), B); tt; --tt) { n = readl(), c = readl() % (mod - 1), k = read(); int res = 0, n1 = (n + 1) % (mod - 1), n2 = (n + 1) % mod; int mt = ksm(tp, c), Mt = ksm(ksm(A, c), k); for (ri t, i = 0; i <= k; ++i) { if (Mt == 1) t = n2; else t = mul(dec(ksm(Mt, n1), 1), Inv(dec(Mt, 1))); (i & 1 ? Dec : Add) (res, mul(t, C(k, i))); Mul(Mt, mt); } cout << mul(res, pw[k]) << '\n'; } return 0; }
Finding a MEX
寫了個根號分治套 \(\text{set}\) 居然過了是我沒想到的,不過由於實現不好會被重邊卡,調了一年...
實際上可以用連結串列做到優美的 \(O(n\sqrt n)\)比賽的時候假胡了一下沒實現,如果不行不要噴我
Code
inline void ins(int x, int v) { if (v > n) return; ++cnt[x][v]; if (cnt[x][v] > 1) return; set <pii> :: iterator it = sg[x].upper_bound(pii(v, n)); --it; pii t = *it; sg[x].erase(it); if (t.fi < v) sg[x].insert(pii(t.fi, v - 1)); if (v < t.se) sg[x].insert(pii(v + 1, t.se)); } inline void del(int x, int v) { if (v > n) return; --cnt[x][v]; if (cnt[x][v]) return; set <pii> :: iterator it = sg[x].upper_bound(pii(v, n)); int l = v, r = v; if (it != sg[x].begin()) { --it; if (it -> se == v - 1) l = it -> fi; ++it; } if (it != sg[x].end()) { if (it -> fi == v + 1) r = it -> se; } sg[x].erase(pii(l, v - 1)); sg[x].erase(pii(v + 1, r)); sg[x].insert(pii(l, r)); } inline void upd(int x, int v) { for (ri i = 1; i <= tot; ++i) if (vs[i][x]) { del(i, a[x]); ins(i, v); } a[x] = v; } inline int qry(int x) { static bool vs[N]; if (id[x]) { x = id[x]; return sg[x].begin() -> fi; } else { for (ri i = 0; i <= blo; ++i) vs[i] = 0; for (ri i = 0; i < e[x].size(); ++i) { int v = a[e[x][i]]; if (v <= blo) vs[v] = 1; } for (ri i = 0; i <= blo; ++i) if (!vs[i]) return i; } } int main() { n = read(), m = read(); for (ri i = 1; i <= n; ++i) a[i] = read(), e[i].clear(), id[i] = 0; for (ri i = 1, u, v; i <= m; ++i) { u = read(), v = read(); e[u].pb(v), e[v].pb(u); } tot = 0; int mx = 0; for (ri i = 1; i <= n; ++i) mx = max(mx, (int) e[i].size()); for (ri i = 1; i <= n; ++i) { sort(e[i].begin(), e[i].end()); e[i].erase(unique(e[i].begin(), e[i].end()), e[i].end()); if (e[i].size() >= blo) { id[i] = ++tot, sg[tot].clear(); for (ri j = 0; j <= n; ++j) cnt[tot][j] = vs[tot][j] = 0; sg[tot].insert(pii(0, n)); for (ri j = 0; j < e[i].size(); ++j) { int v = a[e[i][j]]; vs[tot][e[i][j]] = 1; ins(tot, v); } } } for (ri tt = read(), op, x; tt; --tt) { op = read(), x = read(); if (op == 1) upd(x, read()); else cout << qry(x) << '\n'; } return 0; }
Leading Robots
模擬題意,對給出的二次函式維護出最大值的輪廓就行了。
Code
inline db Cross(int x, int y) { return (B[y] - B[x]) / (K[x] - K[y]); }
inline bool chk(int x, int y, int z) {
db x_0 = Cross(x, y);
return K[x] * x_0 + B[x] <= K[z] * x_0 + B[z];
}
inline bool cmp(int x, int y) { return B[x] < B[y] || (B[x] == B[y] && K[x] < K[y]); }
int main() {
scanf("%d", &n);
for (ri i = 1; i <= n; ++i) scanf("%lf%lf", &B[i], &K[i]), id[i] = i, ban[i] = 0;
sort(id + 1, id + n + 1, cmp);
top = 0;
for (ri i = 1, p; i <= n; ++i) {
p = id[i];
if (top) {
if (make_pair(K[p], B[p]) == make_pair(K[q[top]], B[q[top]])) {
ban[p] = ban[q[top]] = 1;
continue;
}
while (top > 1 && chk(q[top], q[top - 1], p)) --top;
if (top == 1 && K[top] >= K[q[top]]) --top;
}
q[++top] = p;
}
int res = 0;
for (ri i = 1; i <= top; ++i) if (!ban[q[i]]) ++res;
cout << res << '\n';
return 0;
}
Minimum Index
邊做 \(\text{Lyndon}\) 分解邊統計答案即可。
Code
int main() {
n = Read(s);
int ss = 0;
for (ri i = 1; i <= n; ++i) vs[i] = 0;
for (ri i = 1, iv = Inv(1112), j, k, mt = 1; i <= n; ) {
j = i, k = i + 1;
if (!vs[i]) len[i] = 1, vs[i] = 1, Add(ss, mul(mt, i)), Mul(mt, 1112);
for (; k <= n && s[j] <= s[k]; ++k) {
j = s[j] < s[k] ? i : j + 1;
if (!vs[k]) {
vs[k] = 1;
if (i == j) len[k] = k - i + 1;
else len[k] = len[j - 1];
Add(ss, mul(mt, k - len[k] + 1)), Mul(mt, 1112);
}
}
for (; i <= j; i += k - j);
}
cout << ss << '\n';
return 0;
}