比赛链接

A

题解

知识点:数学,构造。

题目要求构造一个长为 \(m\) 的序列 \(c\) ,\(m\) 自选,使得 \(c\) 的无限循环序列 \(b\) 中任意连续 \(a_i\) 个数中都存在数 \(i\) 。因此,容易想到从起点 \(pos_i\) 开始每隔 \(a_i\) 个数就填一次 \(i\) ,即在位置 \((pos_i + ka_i) \mod m , 0\leq k < \frac{m}{a_i}\) ,由此确定了构造的基本方法是填数。

但显然,直接挨个填数很可能会使得某个数的某个落点已经被其他数占据了。比如当 \(a = [5,4]\) 时,考虑构造 \(m=5\) 的序列:先填 \(1\) 得到 \([1,0,0,0,0]\) ,再填 \(2\) 得到 \([1,2,0,0,0]\) ,发现下一个位置是 \(c[0]\) ,已经有数字了。然而事实上,我们不容易在较小的时间复杂度内得到一个合适的起点,使得这个数的落点不会被其他数占据。因此,考虑调整 \(a_i\) ,使得我们可以容易避免落点重合的情况。

证明1

显然,我们只能缩小 \(a_i\) 使得,因为缩小后的 \(a_i\) 满足时原来的 \(a_i\) 一定满足,而放大不一定。

注意到,对于任意两个数 \(a_i\) 与 \(a_j\), 当 \(a_j = da_i,d\geq1\) ,若 \(\exist k,m\) ,使得 \(pos_i + ka_i = pos_j +ma_j\) ,则有 \(pos_j = pos_i + ka_i - ma_j\) ,于是对于 \(\forall m'\),都有 \(pos_j + m'a_j = pos_i + ka_i + (m'-m)a_j = pos_i + [k+(m'-m)d]a_i\) ,即处处重合。

因此,当 \(a_j = da_i\) ,只要一处不重合,则所有落点都不重合。为了方便,将 \(a_i\) 缩小成小于等于它的最大的 \(2\) 的幂 \(a'_i\)。

但仅仅是这样只能保证两两不重合,还无法保证全都不重合。比如当 \(a = [8,8,8,8,4]\) ,考虑 \(m = 8\) ,按顺序填,填到 \(5\) 时会发现 \([1,2,3,4,5,0,0,0]\) ,下一个位置是 \(c[0]\) ,还是被占据了。因此考虑改变填数顺序,使得后一个填的数不会被前面所有的数的位置影响。

证明2

从大到小的就是上述情况,不可行。

考虑从小到大,每次在第一个空位开始填。

由于每次都是从第一个空位填,所以不允许某个 \(a_i'\) 前面填了大于等于 \(a_i'\) 个位置,否则必然会循环回来落到开头被占据的位置,如上述情况。只要我们证明,对于任意一个 \(a_i’\),其前方已经填的位置数 \(x < a_i'\) ,即可。

由于 \(a_i' > \dfrac{a_i}{2}\) ,又条件告诉我们有 \(\sum \frac{1}{a_i} \leq \frac12\) ,那么现在有 $\sum \frac{1}{a_i'} < \sum \frac{2}{a_i} \leq 1 $ 。

当填到 \(a_i' = 2^k\) 时,我们尝试构造 \(a_{1\cdots i-1}' \leq 2^k\) ,使得从 \(0\) 开始连续占用最多的位置。注意到,如果 \(a_j' = 2^ma_i',m\geq 1\),则使用 \(a_i'\) 等效于使用了 \(2^m\) 个 \(a_j'\) ,且总和 \(2^m \frac{1}{a_j'} = \frac{1}{a_i'}\) 也是等价的 ,所以我们按这个方法,无论怎么取,最优结果都是一样的。因此在 \(\sum a_i' \leq 1 \Rightarrow \frac{1}{a_1'} + \cdots + \frac{1}{a_{i-1}'} \leq 1-\frac{1}{2^k}\) 下,为了方便,我们可以优先用小的 \(a_i\) 构造,快速缩小可行范围。

显然,我们只能构造 \(a = [2,4,8,\cdots,2^k]\) ,其倒数总和刚好是 \(1-\frac{1}{2^k}\) ,而连续占用位置是 \(2^k-1\) 个。

于是我们证明了这个结论。

到这里其实最难的两个证明已经结束了。接下来我们思考一下 \(m\) 到底取多少合适。

证明3

长度 \(m\) 时占位为 \(\sum \lceil \frac{m}{a_i'} \rceil\) ,因为每个 \(a_i'\) 对应的 \(i\) 至少出现一次,可得 \(m \geq max(a)\)。

令 \(m = max(a)\) ,带入得 \(\sum \lceil \frac{m}{a_i'} \rceil = \sum \frac{m}{a_i'} \leq m\) ,因此 \(m = max(a)\) 是最小长度。

由于可能多出空位,但是可以随便填,所以全填 \(1\) 。

到此这道构造题就完全结束了。

时间复杂度 \(O(n\log n + max(a))\)

空间复杂度 \(O(n+max(a))\)

代码

#include <bits/stdc++.h>

using namespace std;

struct node {
int val;
int id;
}a[100007];
int c[1000007]; int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin >> n;
for (int i = 1;i <= n;i++) {
cin >> a[i].val;
a[i].id = i;
int tmp = 1 << 30;
while (tmp > a[i].val) tmp >>= 1;
a[i].val = tmp;
}///使用2的幂,证明1
sort(a + 1, a + n + 1, [&](node a, node b) {
return a.val < b.val;
});///从小到大,证明2
int m = a[n].val;///c的长度,证明3
for (int i = 1, pos = 0;i <= n;i++) {
for (int j = pos;j < m;j += a[i].val) c[j] = a[i].id;///方法是填数
while (c[pos]) pos++;
}
cout << m << '\n';
for (int i = 0;i < m;i++) cout << max(1, c[i]) << ' ';///可能多出来空位随便填
cout << '\n';
return 0;
}

B

题解

知识点:枚举,前缀和,差分,树。

考虑树上前缀和与差分。维护当前递归的一条树链的深度到节点编号的映射数组 \(depL\) 即可差分,最后递归求前缀和。

时间复杂度 \(O(n)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>

using namespace std;

vector<int> g[2000007];
int d[2000007];
int dep[2000007], depL[2000007];///节点深度,一条链上深度对应节点
int sum[2000007];///树上差分 void dfs(int u, int fa) {
dep[u] = dep[fa] + 1;
depL[dep[u]] = u;
sum[u]++;
sum[depL[max(0, dep[u] - d[u] - 1)]]--;
for (auto v : g[u]) {
if (v == fa) continue;
dfs(v, u);
}
} void cal(int u, int fa) {
for (auto v : g[u]) {
if (v == fa) continue;
cal(v, u);
sum[u] += sum[v];
}
} int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin >> n;
for (int i = 1;i < n;i++) {
int u, v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
for (int i = 1;i <= n;i++) cin >> d[i];
dfs(1, 0);
cal(1, 0);
for (int i = 1;i <= n;i++) cout << sum[i] << ' ';
cout << '\n';
return 0;
}

G

题解

知识点:模拟。

签到题。直接打表也行,模拟也行。

时间复杂度 \(O(n^2)\)

空间复杂度 \(O(1)\)

代码

#include <bits/stdc++.h>

using namespace std;

int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin >> n; for (int i = 1;i <= 13 * n + 19;i++) cout << '*';
cout << '\n'; for (int i = 1;i <= n;i++) {
cout << "*";
for (int j = 2;j <= 13 * n + 18;j++)
cout << ".";
cout << "*";
cout << '\n';
} for (int i = 1;i <= 2 * n + 3;i++) {
cout << "*";
for (int j = 1;j <= n + 1;j++) cout << ".";
for (int j = 1;j <= 2 * n + 3;j++) {
if (i == 1 || i == 2 * n + 3) {
if (j == 1 || j == 2 * n + 3) cout << "@";
else cout << ".";
}
else {
if (j == 1 || j == 2 * n + 3 || j == i) cout << "@";
else cout << ".";
}
} for (int j = 1;j <= n + 1;j++) cout << "."; for (int j = 1;j <= 2 * n + 3;j++) {
if (i == 1 || i == n + 2) cout << "@";
else {
if (j == 1) cout << "@";
else cout << ".";
}
}
for (int j = 1;j <= n + 1;j++) cout << "."; for (int j = 1;j <= 2 * n + 3;j++) {
if (i == 2 * n + 3) cout << "@";
else {
if (j == 1) cout << "@";
else cout << ".";
}
} for (int j = 1;j <= n + 1;j++) cout << "."; for (int j = 1;j <= 2 * n + 3;j++) {
if (i == 1 || i == n + 2 || i == 2 * n + 3) cout << "@";
else if (1 < i && i < n + 2) {
if (j == 1) cout << "@";
else cout << ".";
}
else if (n + 2 < i && i < 2 * n + 3) {
if (j == 2 * n + 3) cout << "@";
else cout << ".";
}
} for (int j = 1;j <= n + 1;j++) cout << ".";
cout << "*";
cout << '\n';
} for (int i = 1;i <= n;i++) {
cout << "*";
for (int j = 2;j <= 13 * n + 18;j++)
cout << ".";
cout << "*";
cout << '\n';
} for (int i = 1;i <= 13 * n + 19;i++) cout << '*';
cout << '\n';
return 0;
}

J

题解

知识点:思维,数学。

A不能变,B只有A-B与B两个值,于是C的变换方法只有形如交替的A-B与B,而最终C的符号取决于偶数次变换还是奇数次。公式为:

\[\left\{
\begin{aligned}
k(2B-A) +C = x,变换偶次\\
B-k(2B-A)-C = x,变换奇次
\end{aligned}
\right.
\]

这里的 \(k\) 取负时的意义简单理解是交换了变换顺序,比如 \([A-B,B] \rightarrow [B,A]\) 。只要找到整数 \(k\) 满足等式即可,注意 \(2B-A = 0\) 时需要特判。

时间复杂度 \(O(1)\)

空间复杂度 \(O(1)\)

代码

#include <bits/stdc++.h>
#define ll long long using namespace std; bool solve() {
int a, b, c, x;
cin >> a >> b >> c >> x;
if (2 * b - a == 0) {
if (x - c == 0 || x + c - b == 0) cout << "Yes" << '\n';
else return false;
}
else if ((x - c) % (2 * b - a) == 0 || (x + c - b) % (a - 2 * b) == 0) cout << "Yes" << '\n';
else return false;
return true;
} int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
if (!solve()) cout << "No" << '\n';
}
return 0;
}

M

题解

知识点:线性dp,博弈论。

通过转移局面情况到起点,然后判断起点是否到达目标状态。

其中由于走法是固定向下或者向右,所以可以通过横纵坐标之和的奇偶性来决定当前是谁的回合。

对于A而言,两种走法有一种能得到目标状态就转移;对于B而言,两种走法有一种得不到目标状态就转移。

具体看代码注释qwq。

时间复杂度 \(O(nm)\)

空间复杂度 \(O(nm)\)

代码

#include <bits/stdc++.h>
#define ll long long using namespace std; char dt[507][507];
int dp[507][507];
///三种局面是可以独立考虑的,分别看作能否一定走到A、B、(n,m)处状态
///用三位二进制分别表示(i, j)处A是否一定能走到A、B、(n, m)处状态
///1表示一定能走到,0表示不一定能走到(包括一定不)
///已知A处001,终点处为010,B处100 bool solve() {
int n, m;
cin >> n >> m;
for (int i = 1;i <= n;i++)
for (int j = 1;j <= m;j++)
cin >> dt[i][j];
for (int i = n;i >= 1;i--) {
for (int j = m;j >= 1;j--) {
if (dt[i][j] == 'A') { dp[i][j] = 1;continue; }
if (dt[i][j] == 'B') { dp[i][j] = 4;continue; }
if (i == n && j == m) { dp[i][j] = 2;continue; }
if (i == n) dp[i][j] = dp[i][j + 1];
else if (j == m) dp[i][j] = dp[i + 1][j];///无路可走的两种直接传递
else if ((i + j) & 1) dp[i][j] = dp[i + 1][j] & dp[i][j + 1];///可以通过坐标之和奇偶性得知是谁的回合,因为只能往下或者往右走,每轮都只会加一
else dp[i][j] = dp[i + 1][j] | dp[i][j + 1];///每种局面有0则B一定走0,有1则A一定走1
}
}
if (dp[1][1] & 1) cout << "yes" << ' ';
else cout << "no" << ' ';
if (dp[1][1] & 2) cout << "yes" << ' ';
else cout << "no" << ' ';
if (dp[1][1] & 4) cout << "yes" << ' ';
else cout << "no" << ' ';
cout << '\n';
return true;
} int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
if (!solve()) cout << -1 << '\n';
}
return 0;
}

蔚来杯2022牛客暑期多校训练营6 ABGJM的更多相关文章

  1. 蔚来杯2022牛客暑期多校训练营5 ABCDFGHK

    比赛链接 A 题解 知识点:图论,dp. 暴力建图,连接所有点的双向通路,除了原点是单向的,并且把路径长度作为权值. 随后,从原点出发(\(f[0] = 0\),其他点负无穷,保证从原点出发),按照权 ...

  2. 蔚来杯2022牛客暑期多校训练营7 CFGJ

    比赛链接 C 题解 方法一 知识点:思维. 先统计没有出现的数,每个都可以随便放,所以作为补位用的. 将原数组左移一位作为预定的答案数组,然后开始检查.如果和原数组一样,则用补位数字填充,如果不一样就 ...

  3. "蔚来杯"2022牛客暑期多校训练营9 G Magic Spells【马拉车+哈希】

    四川今天又上热搜了,继南部疫情的未雨绸缪后,龙槽沟是真的倾盆大雨了.我没有兴趣虚伪矫情地对罹难的游人表达同情,因为人与人互不相通徒增谈资:我也没有兴趣居高临下地对擅闯的愚人表达不屑,因为你我皆为乌合之 ...

  4. 2019牛客暑期多校训练营(第五场)G - subsequeue 1 (一题我真的不会的题)

    layout: post title: 2019牛客暑期多校训练营(第五场)G - subsequeue 1 (一题我真的不会的题) author: "luowentaoaa" c ...

  5. 2021牛客暑期多校训练营3 J 思维

    传送门 J-Counting Triangles_2021牛客暑期多校训练营3 (nowcoder.com) 题目 Goodeat finds an undirected complete graph ...

  6. B-xor_2019牛客暑期多校训练营(第四场)

    题意 给出n个数组(每组数个数不定),m个询问 l, r, x 序号在区间\([l,r]\)的每个数组是否都可以取出任意个数异或出x 题解 判断一个数组能否异或出x,是简单的线性基问题 判断多个线性基 ...

  7. 2019牛客暑期多校训练营(第九场)A:Power of Fibonacci(斐波拉契幂次和)

    题意:求Σfi^m%p. zoj上p是1e9+7,牛客是1e9:  对于这两个,分别有不同的做法. 前者利用公式,公式里面有sqrt(5),我们只需要二次剩余求即可.     后者mod=1e9,5才 ...

  8. 2019牛客暑期多校训练营(第一场)A题【单调栈】(补题)

    链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 题目描述 Two arrays u and v each with m distinct elem ...

  9. 2019牛客暑期多校训练营(第一场) B Integration (数学)

    链接:https://ac.nowcoder.com/acm/contest/881/B 来源:牛客网 Integration 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 5242 ...

随机推荐

  1. 前端 关于请求地址时出现乱码, 出现%E2%80%8B的问题

    做项目时,添加了新的一个接口,习惯性地复制了接口下来.然后测试发现 请求时自动添加 了几个%E2%80%8B这种乱码. 问题原因: 我输出请求地址时也是正确的,是因为复制过来的接口地址会有零宽空格 解 ...

  2. 关于c#多线程中的几个信号量

    信号量在c#多线程通信中主要用来向阻塞的线程传达信号从而使得阻塞线程继续执行 多线程信号(线程交互):通常是指线程必须等待一个线程或者多个线程通知交互(释放信号)才可以继续执行 在c#中信号量主要有这 ...

  3. Kafka到底有多高可靠?(RNG NB)

    在聊Kafka高可靠之前,先在评论区来波RNG NB好不好! 什么叫可靠性? 大家都知道,系统架构有三高:「高性能.高并发和高可用」,三者的重要性不言而喻. 对于任意系统,想要同时满足三高都是一件非常 ...

  4. python实现一个加密的文字处理器

    这是一个类似于记事本的文字处理器.与正常的记事本不同的是,它会将文本文档进行加密,确保无法被常规的程序打开. 由于本人是一位业余编程爱好者,对于"python之禅"之类的规则比较不 ...

  5. 在项目中如何直接使用hystrix?

    一.背景 最近由于一些背景原因,需要在项目中需要对接口进行限流.所以就考虑到了直接使用Hystrix.但是呢,又不想直接使用SpringCloud,而是直接引入原生,现在发现挺好用的,所以记录下来,分 ...

  6. script标签crossorigin属性及同源策略和跨域方法

    首先介绍(同源策略) 同源策略是浏览器最核心且基本的安全约定,要求协议.域名.端口都相同为同源,如果非同源时请求数据浏览器会在控制台抛出跨域异常错误,同源策略是浏览器的行为,即使客户端请求发送了,服务 ...

  7. 【Java面试】数据库连接池有什么用?它有哪些关键参数?

    一个工作5年的粉丝找到我,他说参加美团面试,遇到一个基础题没回答上来. 这个问题是:"数据库连接池有什么用?以及它有哪些关键参数"? 我说,这个问题都不知道,那你项目里面的连接池配 ...

  8. 解决nginx反向代理Mixed Content和Blockable问题

    nginx配置https反向代理,按F12发现js等文件出现Mixed Content,Optionally-blockable 和 Blockable HTTPS 网页中加载的 HTTP 资源被称之 ...

  9. 使用.NetCore自带的后台作业,出入队简单模拟生产者消费者处理请求响应的数据

    环境:Core:3.1的项目 说明:由于该方案为个人测试项目,重启时队列中的部分数据很可能会丢失, 对数据有要求的该方案不适用,不能照搬需要持久化处理, 另外发布到Linux Docker中通常不会自 ...

  10. Linux 磁盘挂载和swap空间管理

    挂载:把指定的设备和根下面的某个文件夹建立关联 卸载:解除两者关系的过程 挂载文件系统:mount 格式:mount device mountpoint --- mount 设备名 挂载点 mount ...