2018 Multi-University Training Contest 3 Solution
A - Problem A. Ascending Rating
题意:给出n个数,给出区间长度m。对于每个区间,初始值的max为0,cnt为0.遇到一个a[i] > ans, 更新ans并且cnt++。计算
$A = \sum_{i = 1}^{i = n - m +1} (max \oplus i)$
$B = \sum_{i = 1}^{i = n - m +1} (cnt \oplus i)$
思路:单调队列,倒着扫一遍,对于每个区间的cnt就是队列的长度,扫一遍即可。
- #include<bits/stdc++.h>
- using namespace std;
- const int maxn = 1e7 + ;
- typedef long long ll;
- int t;
- int n,m,k;
- ll p, q, r, mod;
- ll arr[maxn];
- ll brr[maxn];
- int main()
- {
- scanf("%d", &t);
- while(t--)
- {
- scanf("%d %d %d %lld %lld %lld %lld", &n, &m, &k, &p, &q, &r, &mod);
- for(int i = ; i <= n; ++i)
- {
- if(i <= k) scanf("%lld", arr + i);
- else arr[i] = (p * arr[i - ] + q * i + r) % mod;
- }
- ll A = , B = ;
- int head = , tail = -;
- for(int i = n; i > (n - m + ); --i)
- {
- while(head <= tail && arr[i] >= arr[brr[tail]]) tail--;
- brr[++tail] = i;
- }
- for(int i = n - m + ; i >= ; --i)
- {
- while(head <= tail && arr[i] >= arr[brr[tail]]) tail--;
- brr[++tail] = i;
- while(brr[head] - i >= m) head++;
- A += arr[brr[head]] ^ i;
- B += (tail - head + ) ^ i;
- }
- printf("%lld %lld\n", A, B);
- }
- return ;
- }
B - Problem B. Cut The String
留坑。
C - Problem C. Dynamic Graph Matching
题意:给出n个点,两种操作,一种是加边,一种是减边,每次加一条或者减一条,每次操作后输出1, 2, ..., n/2 表示对应的数量的边,有几种取法,并且任意两个边不能相邻
思路:每加一条边,都可以转移状态 比如说 110100 到 111110 就是 dp[111110] += dp[110100]
- #include<bits/stdc++.h>
- using namespace std;
- typedef long long ll;
- const int maxn = << ;
- const int MOD = 1e9 + ;
- int t, n, m;
- ll dp[maxn];
- ll ans[];
- inline int cal(int x)
- {
- int cnt = ;
- while(x)
- {
- if(x & ) cnt++;
- x >>= ;
- }
- return cnt;
- }
- int main()
- {
- scanf("%d", &t);
- while(t--)
- {
- memset(ans, , sizeof ans);
- memset(dp, , sizeof dp);
- dp[] = ;
- scanf("%d %d", &n, &m);
- while(m--)
- {
- char op[];
- int u, v;
- scanf("%s %d %d", op, &u, &v);
- --u,--v;
- for(int s = ; s < ( << n); ++s)
- {
- if((s & ( << u)) || (s & ( << v))) continue;
- int S = s | ( << u);
- S |= ( << v);
- if(op[] == '+')
- {
- dp[S] = (dp[S] + dp[s]) % MOD;
- ans[cal(S)] = (ans[cal(S)] + dp[s]) % MOD;
- }
- else if(op[] == '-')
- {
- dp[S] = (dp[S] - dp[s] + MOD) % MOD;
- ans[cal(S)] = (ans[cal(S)] - dp[s] + MOD) % MOD;
- }
- }
- for(int i = ; i <= n; i += )
- {
- printf("%lld%c", ans[i], " \n"[i == n]);
- }
- }
- }
- return ;
- }
D - Problem D. Euler Function
打表找规律
- #include <bits/stdc++.h>
- using namespace std;
- #define N 100010
- inline int gcd(int a, int b)
- {
- return b == ? a : gcd(b, a % b);
- }
- inline void Init()
- {
- for (int i = ; i <= ; ++i)
- {
- int res = ;
- for (int j = ; j < i; ++j)
- res += (gcd(i, j) == );
- printf("%d %d\n", i, res);
- }
- }
- int t, n;
- int main()
- {
- scanf("%d", &t);
- while (t--)
- {
- scanf("%d", &n);
- if (n == ) puts("");
- else printf("%d\n", n + );
- }
- return ;
- }
E - Problem E. Find The Submatrix
留坑,
F - Problem F. Grab The Tree
题意:一棵树,每个点有点权,小Q可以选择若干个点,并且任意两个点之间没有边,小T就是剩下的所有点,然后两个人的值就是拥有的点异或起来,求小Q赢还是输还是平局
思路:显然,只有赢或者平局的情况,只要考虑是否有平局情况就可以,当所有点异或起来为0便是平局
- #include <bits/stdc++.h>
- using namespace std;
- #define N 100010
- int t, n;
- int arr[N];
- int main()
- {
- scanf("%d", &t);
- while (t--)
- {
- scanf("%d", &n);
- int res = ;
- for (int i = ; i <= n; ++i)
- {
- scanf("%d", arr + i);
- res ^= arr[i];
- }
- for (int i = , u, v; i < n; ++i) scanf("%d%d", &u, &v);
- if (res == )
- {
- puts("D");
- continue;
- }
- puts("Q");
- }
- return ;
- }
G - Problem G. Interstellar Travel
题意:给出n个点,要从$i -> j$ 当且仅当 $x_i < x_j$ 花费为 $x_i \cdot y_j - x_j \cdot y_i$ 求从$1 -> n$ 求权值最小如果多解输出字典序最小的解
思路:可以发现权值就是叉积,求个凸包,然后考虑在一条线上的情况
- #include <bits/stdc++.h>
- using namespace std;
- #define N 200010
- const double eps = 1e-;
- inline int sgn(double x)
- {
- if (fabs(x) < eps) return ;
- if (x < ) return -;
- else return ;
- }
- struct Point
- {
- double x, y; int id;
- inline Point () {}
- inline Point(double x, double y) : x(x), y(y) {}
- inline void scan(int _id)
- {
- id = _id;
- scanf("%lf%lf", &x, &y);
- }
- inline bool operator == (const Point &r) const { return sgn(x - r.x) == && sgn(y - r.y) == ; }
- inline bool operator < (const Point &r) const { return x < r.x || x == r.x && y < r.y || x == r.x && y == r.y && id < r.id; }
- inline Point operator + (const Point &r) const { return Point(x + r.x, y + r.y); }
- inline Point operator - (const Point &r) const { return Point(x - r.x, y - r.y); }
- inline double operator ^ (const Point &r) const { return x * r.y - y * r.x; }
- inline double distance(const Point &r) const { return hypot(x - r.x, y - r.y); }
- };
- struct Polygon
- {
- int n;
- Point p[N];
- struct cmp
- {
- Point p;
- inline cmp(const Point &p0) { p = p0; }
- inline bool operator () (const Point &aa, const Point &bb)
- {
- Point a = aa, b = bb;
- int d = sgn((a - p) ^ (b - p));
- if (d == )
- {
- return sgn(a.distance(p) - b.distance(p)) < ;
- }
- return d < ;
- }
- };
- inline void norm()
- {
- Point mi = p[];
- for (int i = ; i < n; ++i) mi = min(mi, p[i]);
- sort(p, p + n, cmp(mi));
- }
- inline void Graham(Polygon &convex)
- {
- sort(p + , p + n - );
- int cnt = ;
- for (int i = ; i < n; ++i)
- {
- if (!(p[i] == p[i - ]))
- p[cnt++] = p[i];
- }
- n = cnt;
- norm();
- int &top = convex.n;
- top = ;
- if (n == )
- {
- top = ;
- convex.p[] = p[];
- convex.p[] = p[];
- return;
- }
- if(n == )
- {
- top = ;
- convex.p[] = p[];
- convex.p[] = p[];
- convex.p[] = p[];
- return ;
- }
- convex.p[] = p[];
- convex.p[] = p[];
- top = ;
- for (int i = ; i < n; ++i)
- {
- while (top > && sgn((convex.p[top - ] - convex.p[top - ]) ^ (p[i] - convex.p[top - ])) >= )
- {
- if(sgn((convex.p[top - ] - convex.p[top - ]) ^ (p[i] - convex.p[top - ])) == )
- {
- if(p[i].id < convex.p[top - ].id) --top;
- else break;
- }
- else
- {
- --top;
- }
- }
- convex.p[top++] = p[i];
- }
- if (convex.n == && (convex.p[] == convex.p[])) --convex.n;
- }
- }arr, ans;
- int t, n;
- int main()
- {
- scanf("%d", &t);
- while (t--)
- {
- scanf("%d", &n); arr.n = n;
- // cout << n << endl;
- for (int i = ; i < n; ++i) arr.p[i].scan(i + );
- arr.Graham(ans);
- for (int i = ; i < ans.n; ++i) printf("%d%c", ans.p[i].id, " \n"[i == ans.n - ]);
- }
- return ;
- }
H - Problem H. Monster Hunter
留坑。
I - Problem I. Random Sequence
留坑。
J - Problem J. Rectangle Radar Scanner
留坑。
K - Problem K. Transport Construction
留坑。
L - Problem L. Visual Cube
按题意模拟即可,分块解决
- #include <bits/stdc++.h>
- using namespace std;
- int t, a, b, c, n, m;
- char ans[][];
- int main()
- {
- scanf("%d", &t);
- while (t--)
- {
- memset(ans, , sizeof ans);
- scanf("%d%d%d", &a, &b, &c);
- n = (b + c) * + ;
- m = (a + b) * + ;
- for (int i = n, cnt = ; cnt <= c; ++cnt, i -= )
- {
- for (int j = ; j <= * a; j += )
- ans[i][j] = '+', ans[i][j + ] = '-';
- }
- for (int i = n - , cnt = ; cnt <= c; ++cnt, i -= )
- {
- for (int j = ; j <= * a; j += )
- ans[i][j] = '|';
- }
- for (int i = * b + , tmp = , cnt = ; cnt <= b + ; ++cnt, i -=, tmp += )
- {
- for (int j = + tmp, cntt = ; cntt <= a; ++cntt, j += )
- ans[i][j] = '+', ans[i][j + ] = '-';
- }
- for (int i = * b, tmp = , cnt = ; cnt <= b; ++cnt, tmp += , i -= )
- {
- for (int j = + tmp, cntt = ; cntt <= a; ++cntt, j += )
- ans[i][j] = '/';
- }
- for (int j = m, cntt = , tmp = ; cntt <= b + ; ++cntt, j -= , tmp += )
- {
- for (int i = + tmp, cnt = ; cnt <= c + ; ++cnt, i += )
- {
- ans[i][j] = '+';
- if (cnt <= c) ans[i + ][j] = '|';
- }
- }
- for (int j = m - , tmp = , cntt = ; cntt <= b; ++cntt, tmp += , j -= )
- {
- for (int i = + tmp, cnt = ; cnt <= c + ; ++cnt, i += )
- ans[i][j] = '/';
- }
- for (int i = ; i <= n; ++i)
- {
- for (int j = ; j <= m; ++j)
- if (!ans[i][j]) ans[i][j] = '.';
- ans[i][m + ] = ;
- printf("%s\n", ans[i] + );
- }
- }
- return ;
- }
M - Problem M. Walking Plan
题意:给出一张图,询问从$u -> v 至少经过k条路的最少花费$
思路:因为$k <= 10000$ 那么我们可以拆成 $k = x * 100 + y$ 然后考虑分块
$G[k][i][j] 表示 i -> j 至少经过k条路$
$dp[k][i][j] 表示 i -> j 至少经过 k * 100 条路$
然后查询的时候枚举中间点
- #include <bits/stdc++.h>
- using namespace std;
- #define N 210
- #define INFLL 0x3f3f3f3f3f3f3f3f
- #define ll long long
- int t, n, m, q;
- ll G[N][][], dp[N][][];
- inline void Init()
- {
- memset(G, 0x3f, sizeof G);
- memset(dp, 0x3f, sizeof dp);
- }
- inline void Floyd()
- {
- for (int l = ; l <= ; ++l)
- for (int k = ; k <= n; ++k)
- for (int i = ; i <= n; ++i)
- for (int j = ; j <= n; ++j)
- G[l][i][j] = min(G[l][i][j], G[l - ][i][k] + G[][k][j]);
- for (int i = ; i <= n; ++i)
- for (int j = ; j <= n; ++j)
- for (int l = ; l >= ; --l)
- G[l][i][j] = min(G[l][i][j], G[l + ][i][j]); // at least K roads;
- for (int i = ; i <= n; ++i)
- for (int j = ; j <= n; ++j)
- dp[][i][j] = G[][i][j];
- for (int l = ; l <= ; ++l)
- for (int k = ; k <= n; ++k)
- for (int i = ; i <= n; ++i)
- for (int j = ; j <= n; ++j)
- dp[l][i][j] = min(dp[l][i][j], dp[l - ][i][k] + dp[][k][j]);
- }
- inline void Run()
- {
- scanf("%d", &t);
- while (Init(), t--)
- {
- scanf("%d%d", &n, &m);
- for (int i = , u, v, w; i <= m; ++i)
- {
- scanf("%d%d%d", &u, &v, &w);
- G[][u][v] = min(G[][u][v], (ll)w);
- }
- Floyd(); scanf("%d", &q);
- for (int i = , u, v, k; i <= q; ++i)
- {
- scanf("%d%d%d", &u, &v, &k);
- int unit = floor (k * 1.0 / ), remind = k - unit * ;
- ll ans = INFLL;
- if (k <= ) ans = G[k][u][v];
- else
- {
- for (int j = ; j <= n; ++j)
- ans = min(ans, dp[unit][u][j] + G[remind][j][v]);
- }
- if (k > && remind == ) ans = min(ans, dp[unit][u][v]);
- printf("%lld\n", ans >= INFLL ? - : ans);
- }
- }
- }
- int main()
- {
- #ifdef LOCAL
- freopen("Test.in", "r", stdin);
- #endif
- Run();
- return ;
- }
2018 Multi-University Training Contest 3 Solution的更多相关文章
- 2018 Multi-University Training Contest 1 Solution
A - Maximum Multiple 题意:给出一个n 找x, y, z 使得$n = x + y +z$ 并且 $n \equiv 0 \pmod x, n \equiv 0 \pmod y, ...
- 2018 Multi-University Training Contest 2 Solution
A - Absolute 留坑. B - Counting Permutations 留坑. C - Cover 留坑. D - Game puts("Yes") #include ...
- 2018 Multi-University Training Contest 4 Solution
A - Problem A. Integers Exhibition 留坑. B - Problem B. Harvest of Apples 题意:计算$\sum_{i = 0}^{i = m}C( ...
- 2018 Multi-University Training Contest 5 Solution
A - Always Online Unsolved. B - Beautiful Now Solved. 题意: 给出一个n, k 每次可以将n这个数字上的某两位交换,最多交换k次,求交换后的最大 ...
- 2018 Multi-University Training Contest 6 Solution
A - oval-and-rectangle 题意:给出一个椭圆的a 和 b,在$[0, b]中随机选择c$ 使得四个顶点在椭圆上构成一个矩形,求矩形周长期望 思路:求出每种矩形的周长,除以b(积分) ...
- 2018 Multi-University Training Contest 7 Solution
A - Age of Moyu 题意:给出一张图,从1走到n,如果相邻两次走的边的权值不同,花费+1, 否则花费相同,求最小花费 思路:用set记录有当前点的最小花费有多少种方案到达,然后最短路 #i ...
- 2018 Multi-University Training Contest 8 Solution
A - Character Encoding 题意:用m个$0-n-1$的数去构成k,求方案数 思路:当没有0-n-1这个条件是答案为C(k+m-1, m-1),减去有大于的关于n的情况,当有i个n时 ...
- 2018 Multi-University Training Contest 9 Solution
A - Rikka with Nash Equilibrium 题意:构造一个$n * m$的矩阵,使得$[1, n * m]$ 中每个数只出现一次,并且纳什均衡只出现一次. 思路:从大到小的放置,每 ...
- 2018 Multi-University Training Contest 10 Solution
A - Problem A.Alkane 留坑. B - Problem B. Beads 留坑. C - Problem C. Calculate 留坑. D - Problem D. Permut ...
随机推荐
- ssh通过密钥进行连接
sshd服务提供两种安全验证的方法: 基于口令的安全验证:经过验证帐号与密码即可登陆到远程主机. 基于密钥的安全验证:需要在本地生成"密钥对"后将公钥传送至服务端,进行公共密钥的比 ...
- EventBus 简单原理(一)
EventBus 1.根据文章最前面所讲的EventBus使用步骤,首先我们需要定义一个消息事件类: public class MessageEvent { private String messag ...
- vue.js2.0+elementui ——> 后台管理系统
前言: 因为观察到vue.js的轻量以及实时更新数据的便捷性,于是新项目便决定使用vue.js2.0以及与之配套的elementui来完成.只是初次接触新框架,再使用过程中,遇见了各种各样“奇葩”的问 ...
- C++的virtual详解
类的多态特性是支持面向对象的语言最主要的特性,有过非面向对象语言开发经历的人,通常对这一章节的内容会觉得不习惯,因为很多人错误的认为,支持类的封装的语言就是支持面向对象的,其实不然,Visual BA ...
- GMT时间转换为当地时间的方法
1.取得当地时间与GMT时间的时间差 (new Date()).getTimezoneOffset() //单位为分钟 2.GMT时间加上与当地时间的时间差 (new Date(GMTTime)) ...
- 如何实现UI层的松耦合
UI层的松耦合主要是指html.css.js的松耦合 1. 将js代码从css中分离,即不使用expression 2. 将css从js中分离,尽量不要在js中直接操作css.如果需要操作,可以使 ...
- Python subprocess shell 编程规范
使用subprocess通过shell调用另一个模块组件时,需要对返回的code进行判断.判断结果为执行失败时需要raise Exception,不然调用树过于复杂时,我们很难跟踪到异常发生的位置.s ...
- javascript关于链接的一些用法
(1)javascript:openURL() http://www.kpdown.com/search?name=Ben Nadel 此URL后边有一个name参数,只不过参数的值竟然带了空格,这样 ...
- 什么是runtime?什么是webgl?
一 什么是Runtime? Egret官方解释:https://www.egret.com/products/runtime.html 二.什么是WebGL渲染? egret官方解释:http://d ...
- Egret Wing4.0.3 合并资源图片问题
一 发布项目时,选择合并图片资源 选择合图大小 发布后,图片合并.随机了图片名字. 二 随机名的问题 当资源不变更的情况下,多次发布,每次发布后资源的图片随机名是不变的. 现在改变preload组 ...