May Cook-Off 2019 解题报告
太气了。Atcoder unrated了。
这一场时间太不友好了。昨天下午一时兴起就去补了一发。题很好,学到好多东西。
题意:给一个矩阵,这个矩阵是稳定的当且仅当每一个元素都是稳定的。元素是稳定的当且仅当它的值严格小于它相邻有几个元素
思路:四个角的值就必须小于2,然后外圈的其他数的值就必须小于3,其他的就必须小于4。
#include <bits/stdc++.h>
using namespace std; inline int read() {
int x = , f = ; char ch = getchar();
while (ch < '' || ch > '') { if (ch == '-') f = -; ch = getchar(); }
while (ch >= '' && ch <= '') { x = x * + ch - ; ch = getchar(); }
return x * f;
} const int N = ;
int a[N][N]; int main() {
int T = read();
while (T--) {
int r = read(), c = read();
bool ans = false;
for (int i = ; i <= r; i++) {
for (int j = ; j <= c; j++) {
a[i][j] = read();
if (i == ) {
if (i == j || j == c) {
if (a[i][j] >= ) ans = true;
} else {
if (a[i][j] >= ) ans = true;
}
} else if (i == r) {
if ( == j || j == c) {
if (a[i][j] >= ) ans = true;
} else {
if (a[i][j] >= ) ans = true;
}
} else if (j == || j == c) {
if (a[i][j] >= ) ans = true;
} else {
if (a[i][j] == ) ans = true;
}
}
}
if (ans) puts("Unstable");
else puts("Stable");
}
}
题意:一个等差数列,其中一个数被改了,要求原数列。
思路:四项肯定可以出一个等差数列,只看前四项就ok了。
#include <bits/stdc++.h>
using namespace std; inline int read() {
int x = , f = ; char ch = getchar();
while (ch < '' || ch > '') { if (ch == '-') f = -; ch = getchar(); }
while (ch >= '' && ch <= '') { x = x * + ch - ; ch = getchar(); }
return x * f;
} const int N = 1e5 + ;
int a[N], b[N]; int main() {
int T = read();
while (T--) {
int n = read();
for (int i = ; i <= n; i++) a[i] = read();
if (a[] - a[] == a[] - a[]) {
int d = a[] - a[];
for (int i = ; i <= n; i++) {
a[i] = a[i-] + d;
}
} else if (a[] - a[] == a[] - a[]) {
int d = a[] - a[];
for (int i = n - ; i > ; i--) {
a[i] = a[i+] - d;
}
} else {
int d = (a[] - a[]) / ;
for (int i = ; i <= n; i++) {
a[i] = a[i - ] + d;
}
}
for (int i = ; i <= n; i++) { if (i - ) putchar(' '); printf("%d", a[i]); }
puts("");
}
return ;
}
题意:给一个区间$l,r$和一个数$g$,要求这个区间内最多有几个数的GCD刚好为$g$
思路:容斥求,WA了好几发,原因是。当容斥出来结果只有1个时,$g$必须在$l,r$之间,不然这一个数的最大因子是自己而不是$g$。
题目描述也是The greatest positive integer which divides each element of the set is exactly $g$,一个数的greatest positive integer which divide it是它本身。
#include <bits/stdc++.h>
#define ll long long
using namespace std; inline ll readl() {
ll x = , f = ; char ch = getchar();
while (ch < '' || ch > '') { if (ch == '-') f = -; ch = getchar(); }
while (ch >= '' && ch <= '') { x = x * + ch - ; ch = getchar(); }
return x * f;
} int main() {
ll T = readl();
while (T--) {
ll l = readl(), r = readl(), g = readl();
ll ans = r / g - l / g + (l % g == );
if (ans == ) {
if (g < l || g > r) ans = ;
}
printf("%lld\n", ans);
}
return ;
}
题意:给一个有向图,问能不能删边删点使他们成为一个二分图 一边点数为2,一边点数为$k$
思路:暴力求。不知道为啥不会T。咱也不知道,咱也不敢问。
#include <bits/stdc++.h>
using namespace std; inline int read() {
int x = , f = ; char ch = getchar();
while (ch < '' || ch > '') { if (ch == '-') f = -; ch = getchar(); }
while (ch >= '' && ch <= '') { x = x * + ch - ; ch = getchar(); }
return x * f;
} const int N = 2e3 + ;
vector<int> G[N]; int main() {
int n = read(), m = read(), k = read();
for (int i = ; i < m; i++) {
int u = read(), v = read();
G[u].emplace_back(v);
G[v].emplace_back(u);
}
for (int i = ; i <= n; i++) sort(G[i].begin(), G[i].end());
for (int i = ; i <= n; i++) {
for (int j = i + ; j <= n; j++) {
int p1 = , p2 = ;
int ans = ;
int sz1 = G[i].size(), sz2 = G[j].size();
while (p1 < sz1 && p2 < sz2) {
if (G[i][p1] == G[j][p2]) {
p1++;p2++; ans++;
} else if (G[i][p1] < G[j][p2]) {
p1++;
} else p2++;
}
if (ans >= k) { puts("YES"); return ;}
}
}
puts("NO");
return ;
}
看了题解的解法。复杂度就比较科学了。$O\left( n^{2}k\right)$
#include <bits/stdc++.h>
using namespace std; inline int read() {
int x = , f = ; char ch = getchar();
while (ch < '' || ch > '') { if (ch == '-') f = -; ch = getchar(); }
while (ch >= '' && ch <= '') { x = x * + ch - ; ch = getchar(); }
return x * f;
} const int N = 2e3 + ;
vector<int> G[N];
int cnt[N][N]; int main() {
int n = read(), m = read(), k = read();
for (int i = ; i < m; i++) {
int u = read(), v = read();
G[u].emplace_back(v);
G[v].emplace_back(u);
}
bool ans = false;
for (int i = ; i <= n; i++) {
if (ans) break;
for (auto x: G[i]) {
if (ans) break;
for (auto y: G[i]) {
if (x < y) {
cnt[x][y]++;
cnt[y][x]++;
}
if (cnt[x][y] >= k) {
ans = true;
break;
}
}
}
}
if (ans) puts("YES");
else puts("NO");
return ;
}
题意:给n个物品,每个物品有值$b_{i}$和选中概率$p_{i}$,求异或和的期望
思路:emmmm概率题本来就不太会再加上异或emmmmm
按位考虑每一个数,因为异或是两个相同就变成0了。那么能对期望做出贡献的时候就是二选一的时候
pro表示在当前位,当前数能对期望做出贡献的概率。
到下一个数的时候就是$pro\ast \left( 1-p_{i}\right) + p_{i}\ast \left( 1-pro\right)$
最后乘上(1 << k) 就行了 k表示当前位
#include <bits/stdc++.h>
using namespace std; inline int read() {
int x = , f = ; char ch = getchar();
while (ch < '' || ch > '') { if (ch == '-') f = -; ch = getchar(); }
while (ch >= '' && ch <= '') { x = x * + ch - ; ch = getchar(); }
return x * f;
} const int N = 1e5 + ;
int b[N], n;
double p[N]; int main() {
int T; scanf("%d", &T);
while (T--) {
scanf("%d", &n);
for (int i = ; i < n; i++) scanf("%d", &b[i]);
for (int i = ; i < n; i++) scanf("%lf", &p[i]);
long double ans = ;
for (int bit = ; bit < ; bit++) {
long double pro = ;
for (int i = ; i < n; i++) {
if ((b[i] >> bit) & ) {
pro = ( - pro) * (long double)p[i] + pro * ( - (long double)p[i]);
}
}
ans += ( << bit) * pro;
}
printf("%.7Lf\n", ans);
}
return ;
}
题意:有节点0到$2^{k} - 1$,给一个序列$m_{i}$ ,所有点对$u,v$ $u\oplus v = m_{i}$的之间连边,问最后有多少个连通块
思路:推了半天结论也没推明白。看题解才明白是高斯消元。
对于一个节点$u$,它能到达的点是这个序列的数,任意组合,异或之后的值的个数(加上一个0)
本来是只能异或这个序列里面的一个数,但是由于别的数也会异或,就会连通了。
比如两个节点1 和 2
$m_{1} = 1$ $m_{2} = 2$
1和$m_{1}$异或后是0 和$m_{2}$异或后是3 2和$m_{1}$异或后是3
本来只异或一个值的话,1和2看起来是不连通的
但就是会间接相连 所以就是xjb组合着去异或
然后答案就是看这个序列能异或出多少种值来。
把它们按二进制排成一个矩阵。
求出这个矩阵的秩$r$
答案就是$2^{k - r}$
解释:把矩阵通过异或运算变成行阶梯型之后,秩为$r$,前$r$行的线性组合得到的结果必是不一样了
然后取和不取种类数就是$2^{r}$种
#include <bits/stdc++.h>
using namespace std; inline int read() {
int x = , f = ; char ch = getchar();
while (ch < '' || ch > '') { if (ch == '-') f = -; ch = getchar(); }
while (ch >= '' && ch <= '') { x = x * + ch - ; ch = getchar(); }
return x * f;
} const int N = 1e5 + ;
int a[N];
int bin[N]; int main() {
int T = read();
while (T--) {
memset(bin, , sizeof(bin));
int k = read(), m = read();
for (int i = ; i < m; i++) {
int x = read();
for (int j = ; j < ; j++) {
if ((<<j) & x) {
if (!bin[j]) {
bin[j] = x;
k--;
break;
}
x ^= bin[j];
}
}
}
cout << ( << k) << '\n';
}
return ;
}
题意:一棵树,刚开始只有根1和颜色$c$,给$Q$次询问,询问有两种,第一种是给节点$u$加上一个儿子(编号为当前节点数+1),颜色染成$c$,第二种询问颜色为$c$的节点中,和$u$最近的距离是多少。
思路:直接写了发暴力找+倍增LCA,T了。看了题解才发现有trick。
把颜色分为大和小。以300次为界限。
出现次数小于300的就可以直接暴力+LCA
大于300的把颜色为$c$的节点$u$ $dis[c][u] = 0$并且对这些节点进行bfs
bfs过程中若dis为INF的话就可以更新成$dis[c][u] + 1$
#include <bits/stdc++.h>
using namespace std; inline int read() {
int x = , f = ; char ch = getchar();
while (ch < '' || ch > '') { if (ch == '-') f = -; ch = getchar(); }
while (ch >= '' && ch <= '') { x = x * + ch - ; ch = getchar(); }
return x * f;
} const int N = 2e5 + ;
const int RT = ;
const int INF = 0x3f3f3f3f;
vector<int> group[N];
vector<int> rem[N];
vector<int> big;
vector<int> adj[N];
vector<int> dis[N];
int fa[N], lca[N][], n, dep[N], q, col[N]; void recalc(int c) {
if (dis[c].empty()) big.emplace_back(c);
dis[c].assign(n + , N);
queue<int> que;
for (int u: group[c]) {
dis[c][u] = ;
que.push(u);
}
while (!que.empty()) {
int u = que.front(); que.pop();
for (int v: adj[u]) {
if (dis[c][v] == N) {
dis[c][v] = dis[c][u] + ;
que.push(v);
}
}
}
rem[c].clear();
} void add(int u, int c) {
n++;
col[n] = c;
lca[n][] = fa[n] = u;
adj[n].emplace_back(u);
adj[u].emplace_back(n);
dep[n] = dep[u] + ;
for (int i = ; i <= ; i++) lca[n][i] = lca[lca[n][i-]][i-];
for (int cc: big) dis[cc].emplace_back(dis[cc][u] + );
group[c].emplace_back(n);
rem[c].emplace_back(n);
if (rem[c].size() >= RT) recalc(c);
} int Lca(int u, int v) {
if (dep[u] < dep[v]) swap(u, v);
int f = dep[u] - dep[v];
for (int i = ; i <= ; i++) {
if (f & ( << i)) {
u = lca[u][i];
}
}
if (u == v) return v;
for (int i = ; i >= ; i--) {
if (lca[u][i] != lca[v][i]) {
u = lca[u][i];
v = lca[v][i];
}
}
return lca[u][];
} int distance(int u, int v) {
return dep[u] + dep[v] - * dep[Lca(u, v)];
} int query(int u, int c) {
int ans = dis[c].size() ? dis[c][u] : N;
for (int v: rem[c]) ans = min(ans, distance(u, v));
if (ans == N) ans = -;
return ans;
} void init() {
for (int i = ; i < N; i++) {
adj[i].clear();
group[i].clear();
dis[i].clear();
rem[i].clear();
}
big.clear();
n = ;
} int main() {
int T = read();
while (T--) {
init();
q = read();int c = read();
group[c].emplace_back();
rem[c].emplace_back();
dep[] = ; fa[] = ;
int a = -;
while (q--) {
char s[];
scanf("%s", s);
int u = read(); c = read();
u = u ^ (a + ); c = c ^ (a + );
if (s[] == '+') add(u, c);
else printf("%d\n", a = query(u, c));
}
}
return ;
}
还是太菜了呀...
May Cook-Off 2019 解题报告的更多相关文章
- 【LeetCode】236. Lowest Common Ancestor of a Binary Tree 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...
- 【LeetCode】684. Redundant Connection 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 并查集 日期 题目地址:https://leetco ...
- 【LeetCode】817. Linked List Components 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...
- 【LeetCode】90. Subsets II 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 回溯法 日期 题目地址:https://leet ...
- CH Round #56 - 国庆节欢乐赛解题报告
最近CH上的比赛很多,在此会全部写出解题报告,与大家交流一下解题方法与技巧. T1 魔幻森林 描述 Cortana来到了一片魔幻森林,这片森林可以被视作一个N*M的矩阵,矩阵中的每个位置上都长着一棵树 ...
- 二模13day1解题报告
二模13day1解题报告 T1.发射站(station) N个发射站,每个发射站有高度hi,发射信号强度vi,每个发射站的信号只会被左和右第一个比他高的收到.现在求收到信号最强的发射站. 我用了时间复 ...
- BZOJ 1051 最受欢迎的牛 解题报告
题目直接摆在这里! 1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4438 Solved: 2353[S ...
- 习题:codevs 2822 爱在心中 解题报告
这次的解题报告是有关tarjan算法的一道思维量比较大的题目(真的是原创文章,希望管理员不要再把文章移出首页). 这道题蒟蒻以前做过,但是今天由于要复习tarjan算法,于是就看到codevs分类强联 ...
- 习题:codevs 1035 火车停留解题报告
本蒟蒻又来写解题报告了.这次的题目是codevs 1035 火车停留. 题目大意就是给m个火车的到达时间.停留时间和车载货物的价值,车站有n个车道,而火车停留一次车站就会从车载货物价值中获得1%的利润 ...
随机推荐
- IntelliJ IDEA 删除自定义的 Maven 框架依赖
IntelliJ IDEA 删除自定义的 Maven 框架依赖 IntelliJ Idea中添加Maven Archetype,但是IntelliJ Idea中并没有提供删除的方法. windows中 ...
- day24——面向对象三大特性、鸭子类型、类的约束、super的深度解析
day24 面向对象的三大特性 继承.封装.多态 封装:把一堆东西(代码,数据)放到一个地方(空间),并且可以使用 class Student: def __init__(self, name, se ...
- 【LEETCODE】61、对leetcode的想法&数组分类,适中级别,题目:162、73
这几天一直再想这样刷题真的有必要么,这种单纯的刷题刷得到尽头么??? 这种出题的的题目是无限的随便百度,要多少题有多少题,那么我这一直刷的意义在哪里??? 最近一直苦苦思考,不明所以,刷题刷得更多的感 ...
- ubuntu 安装Jenkins
一.介绍 Jenkins是一款开源自动化服务器,旨在自动化连续集成和交付软件所涉及的重复技术任务. Jenkins是基于Java的,可以从Ubuntu软件包安装,也可以通过下载和运行其Web应用程序A ...
- python_dict json读写文件
命令汇总: json.dumps(obj) 将python数据转化为json Indent实现缩进,ensure_ascii 是否用ascii解析 json.loads(s) 将json数据转换为py ...
- react-navigation 的抽屉效果 createDrawerNavigator (DrawerNavigator)
一.前言: react-navigation 3.x 版本中, 使用createDrawerNavigator 替换 原先的DrawerNavigator 方法: 那么,当前createBottom ...
- 4.将验证添加到 ASP.NET Core Razor 页面
向 Movie 模型添加了验证逻辑. 每当用户创建或编辑电影时,都会强制执行验证规则. 1.打开Movie.cs文件.DataAnnotations命名空间提供了一组内置的验证属性,这些属性以声明方式 ...
- 用lua求两个数组的交集、并集和补集。
-- 克隆 function Clone(object) local lookup_table = { } local function _copy(object) if type(object) ~ ...
- Navicat 导出 表结构
Navicat 导出 表结构 转自:https://www.cnblogs.com/xianxiaobo/p/10254737.html 1. 首先点击新建查询,然后输入下面的语句 SELECT CO ...
- 【开发工具】- 推荐一款好用的文本编辑器[Sublime Text]
作为一个程序员除了IDE外,文本编辑器也是必不可少的一个开发工具.之前一直在用的是NotePad++.EditPlus,这两款编辑器,但是总感觉差点什么,昨天在知乎上看到有人推荐Sublime Tex ...