2020 Multi-University Training Contest 1 部分题解
Cookies
先简单二分出最后查的是哪个标号。
然后发现这个可以快速处理出一段区间的答案,分段打表即可。
注意代码长度限制不要爆了我就白打了 10min
Code
ll n, k, a[N];
ll S[4001] = { ... };
int m;
inline ll cal(ll x) {
for (ri i = 1; i <= m && x >= k; ++i) x -= x / a[i];
return x;
}
inline ll Cal(ll l, ll r) {
static int divv[Bas + 5], len;
len = r - l;
for (ri i = 0; i <= len; ++i) divv[i] = 1;
for (ri i = 2; (ll) i * i <= r; ++i) for (ri j = max((ll) i, (l + i - 1) / i) * i - l; j <= len; j += i)
divv[j] = i;
ll res = 0;
for (ri i = 0; i <= len; ++i) res += divv[i];
return res;
}
namespace Biao {
inline void get_Biao() {
cout << "ll S[] = { 0";
ll l = 1, r = Bas;
for (ri i = 1; i <= 4000; ++i, l += Bas, r += Bas) cout << ", " << Cal(l, r);
cout << " };\n";
exit(0);
}
}
int main() {
//Biao:: get_Biao();
for (ri i = 1; i <= 4000; ++i) S[i] += S[i - 1];
n = readl(), m = read(), k = readl();
for (ri i = 1; i <= m; ++i) a[i] = readl();
if (cal(n) < k) { puts("-1"); continue; }
ll L = 0, R = n, p = n;
while (L <= R) {
ll mid = (L + R) >> 1;
if (cal(mid) >= k) p = mid, R = mid - 1;
else L = mid + 1;
}
if (cal(n) < k) {
cout << -1 << '\n';
continue;
}
if (p % Bas <= Bas / 2) {
ll res = Cal(p / Bas * Bas + 1, p);
res += S[p / Bas];
cout << res << '\n';
}
else {
ll res = -Cal(p + 1, (p / Bas + 1) * Bas);
res += S[p / Bas + 1];
cout << res << '\n';
}
return 0;
}
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;
}
Math is Simple
\(\large{\text{Math is not Simple}}\)
设题目要求的是 \(f_n\),然后 \(g_n=\sum\limits_{1\le a<b\le n,\gcd(a,b)=1,a+b=n}\frac1{ab}\),将 \(f_n\) 和 \(f_{n-1}\) 做差。
发现 \(f_n=f_{n-1}+g_n-g_{n-1}=\cdots=g_n+\frac12\)
这个 \(g\) 可以莫反算,这题就解决了。
Code
int main() {
int Lm = 1e8, _Lm = 10000;
inv[1] = 1;
for (ri i = 2; i <= Lm; ++i) inv[i] = mul(inv[mod - mod / i * i], mod - mod / i);
for (ri i = 2; i <= Lm; ++i) Add(inv[i], inv[i - 1]);
for (ri i = 2; i <= _Lm; ++i) {
if (!vs[i]) pri[++tot] = i;
for (ri j = 1; j <= tot && i * pri[j] <= _Lm; ++j) {
vs[i * pri[j]] = 1;
if (i == i / pri[j] * pri[j]) break;
}
}
int iv2 = (mod + 1) >> 1;
n = read();
int x = n;
vector <int> divv;
for (ri i = 1; i <= tot && pri[i] * pri[i] <= x; ++i) if (x == x / pri[i] * pri[i]) {
divv.pb(pri[i]);
while (x == x / pri[i] * pri[i]) x /= pri[i];
}
if (x ^ 1) divv.pb(x);
int res = 0, lm = 1 << divv.size();
vector <int> Divv(lm);
if (n > 2) for (ri s = 0; s < lm; ++s) {
Divv[s] = s ? Divv[s - (s & -s)] * divv[__builtin_ctz(s)] : 1;
int Miu = __builtin_popcount(s) & 1 ? mod - 1 : 1;
Add(res, mul(mul(Miu, inv[n / Divv[s]]), dec(inv[Divv[s]], inv[Divv[s] - 1])));
}
cout << add(mul(res, dec(inv[n], inv[n - 1])), iv2) << '\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;
}
Mow
维护一下半平面交即可。
调了半个上午都没调出来,最后发现好像是 \(\text{hdu}\) 不支持用 \(\text{printf}\) 输出 \(\text{long double}\) 类型的答案...
Code
inline bool cmp(Line x, Line y) { return x.ang < y.ang; }
inline pt Cross(Line a, Line b) {
db s1 = (a.a - b.a) * (a.b - b.a), s2 = (a.b - b.b) * (a.a - b.b), t = s1 / (s1 + s2);
return b.a + (b.b - b.a) * t;
}
inline bool chk(Line x, Line y, Line z) {
pt tp = Cross(x, y);
return (z.b - z.a) * (tp - z.a) <= 0;
}
const db pi = acosl(-1.0);
inline db calc() {
static int q[N], hd, tl;
static pt A[N];
sort(L + 1, L + n + 1, cmp);
hd = 1, tl = 0;
for (ri i = 1; i <= n; ++i) {
while (hd < tl && chk(L[q[tl]], L[q[tl - 1]], L[i])) --tl;
while (hd < tl && chk(L[q[hd]], L[q[hd + 1]], L[i])) ++hd;
q[++tl] = i;
}
while (hd < tl && chk(L[q[tl]], L[q[tl - 1]], L[q[hd]])) --tl;
while (hd < tl && chk(L[q[hd]], L[q[hd + 1]], L[q[tl]])) ++hd;
if (tl - hd + 1 < 3) return 0;
q[tl + 1] = q[hd];
int ct = 0;
for (ri i = hd; i <= tl; ++i) A[++ct] = Cross(L[q[i]], L[q[i + 1]]);
A[ct + 1] = A[1];
db res = 0, ss = 0;
for (ri i = 1; i <= ct; ++i) res += A[i] * A[i + 1], ss += (A[i + 1] - A[i]).mod();
res *= 0.5l, res += ss * R;
return res + pi * R * R;
}
int main() {
n = read(), R = read(), A = read(), B = read();
for (ri i = 1; i <= n; ++i) a[i].x = read(), a[i].y = read();
a[n + 1] = a[1];
db S = 0, res;
for (ri i = 1; i <= n; ++i) S += a[i] * a[i + 1];
S *= 0.5l;
if (S < 0) {
S = -S;
reverse(a + 1, a + n + 1);
a[n + 1] = a[1];
}
res = S * A;
if (A <= B) {
cout << fixed << setprecision(20) << res << '\n';
continue;
}
for (ri i = 1; i <= n; ++i) {
pt tp = a[i + 1] - a[i];
db ang = atan2l(tp.y, tp.x);
tp = pt(-tp.y, tp.x);
tp /= tp.mod(), tp *= R;
L[i] = (Line) { a[i] + tp, a[i + 1] + tp, ang };
}
res -= (A - B) * calc();
cout << fixed << setprecision(20) << res << '\n';
return 0;
}
2020 Multi-University Training Contest 1 部分题解的更多相关文章
- 2018 Multi-University Training Contest 3(部分题解)
Problem F. Grab The Tree Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 524288/524288 K (Ja ...
- 2018 Multi-University Training Contest 2(部分题解)
Game Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submi ...
- 2018 Multi-University Training Contest 1(部分题解)
Maximum Multiple Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- 2016 Multi-University Training Contest 3 部分题解
1001,只要枚举区间即可.签到题,要注意的是输入0的话也是“TAT”.不过今天补题的时候却WA了好几次,觉得奇怪.原来出现在判断条件那里,x是一个int64类型的变量,在进行(x<65536* ...
- 2016 Multi-University Training Contest 1 部分题解
第一场多校,出了一题,,没有挂零还算欣慰. 1001,求最小生成树和,确定了最小生成树后任意两点间的距离的最小数学期望.当时就有点矛盾,为什么是求最小的数学期望以及为什么题目给了每条边都不相等的条件. ...
- 2016 Multi-University Training Contest 4 部分题解
1001,官方题解是直接dp,首先dp[i]表示到i位置的种类数,它首先应该等于dp[i-1],(假设m是B串的长度)同时,如果(i-m+1)这个位置开始到i这个位置的这一串是和B串相同的,那么dp[ ...
- 2018 Multi-University Training Contest - Team 1 题解
Solved A HDU 6298 Maximum Multiple Solved B HDU 6299 Balanced Sequence Solved C HDU 6300 Triangle Pa ...
- 2016 Multi-University Training Contest 2 部分题解
1009,直接贪心,只要让后面的尽量小,第一位和第二位尽量大即可. 1011,直接统计奇数的字母的个数,然后用偶数的个数平均分配到它们上面即可.代码如下: #include <stdio.h&g ...
- 【多校】2019 Multi-University Training Contest 1官方题解
Blank 定义dp[i][j][k][t]dp[i][j][k][t]dp[i][j][k][t]代表填完前ttt个位置后,{0,1,2,3}\{0,1,2,3\}{0,1,2,3}这4个数字最后一 ...
随机推荐
- Django框架12 /同源、跨域、CORS
Django框架12 /同源.跨域.CORS 目录 Django框架12 /同源.跨域.CORS 1. 同源策略 2. 跨域 3. 解决跨域:CORS/跨域资源共享 1. 同源策略 同源策略(Same ...
- bzoj1640[Usaco2007 Nov]Best Cow Line 队列变换*&&bzoj1692[Usaco2007 Dec]队列变换*
bzoj1640[Usaco2007 Nov]Best Cow Line 队列变换 bzoj1692[Usaco2007 Dec]队列变换 题意: 有一个奶牛队列.每次可以在原来队列的首端或是尾端牵出 ...
- Go的100天之旅-常量
常量 简介 道可道,非常道.这里常道指的永恒不变的道理,常有不变的意思.顾名思义和变量相比,常量在声明之后就不可改变,它的值是在编译期间就确定的. 下面简单的声明一个常量: const p int = ...
- selenium自动化测试实战——12306铁路官网范例
一.Selenium介绍 Selenium 是什么?一句话,自动化测试工具.它支持各种浏览器,包括 Chrome,Safari,Firefox 等主流界面式浏览器,如果你在这些浏览器里面安装一个 Se ...
- Jexl表达式引擎-根据字符串动态执行JAVA.md
Table of Contents generated with DocToc 一.使用场景 二.市面上表达式引擎比较 2.1 Aviator 2.2 Jexl 一.使用场景 在做某些项目的时候,有时 ...
- 设计模式:command模式
目的:将命令设计成类的形式,并可以组织成队列 优点: 在需要的情况下,可以比较容易地将命令记入日志 可以容易的实现对请求的撤销和重做 由于新的具体命令类不影响其他的命令类,因此增加新的具体命令类很容易 ...
- [spring] -- bean作用域跟生命周期篇
作用域 singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的. prototype : 每次请求都会创建一个新的 bean 实例. request : 每一次HT ...
- 题解 洛谷 P4694 【[PA2013]Raper】
首先考虑题目的性质,不难发现光盘的花费是一个凸函数.当生产 \(0\) 张光盘时,其花费为 \(0\),随着光盘生产数的增加,最优情况肯定是先选择工厂便宜的时刻,所以花费会增长越来越快,因此其为一个下 ...
- 题解 CF938G 【Shortest Path Queries】
题目让我们维护一个连通无向图,边有边权,支持加边删边和询问从\(x\)到\(y\)的异或最短路. 考虑到有删边这样的撤销操作,那么用线段树分治来实现,用线段树来维护询问的时间轴. 将每一条边的出现时间 ...
- Python 实现将numpy中的nan和inf,nan替换成对应的均值
nan:not a number inf:infinity;正无穷 numpy中的nan和inf都是float类型 t!=t 返回bool类型的数组(矩阵) np.count_nonzero( ...