比赛链接

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. 118_Power Pivo周维度度同比、环比相关

    博客:www.jiaopengzi.com 焦棚子的文章目录 请点击下载附件 一.背景 在群里看到有人在交流周维度同环比,同时又好多天都没有更新文章了,最近没有什么好的素材,就硬生生的写一个吧. 先来 ...

  2. TornadoFx设置保存功能((config和preference使用))

    原文地址:TornadoFx设置保存功能(config和preference使用) 相信大部分的桌面软件都是存在一个设置的界面,允许用户进行设置的修改,此修改之后需要保存的本地,若是让开发者自己实现, ...

  3. Pandas:添加修改、高级过滤

    1.添加修改数据 Pandas 的数据修改是进行赋值,先把要修改的数据筛选出来,然后将同结构或者可解包的数据赋值给它: 修改数值 df.Q1 = [1, 3, 5, 7, 9] * 20 # 就会把值 ...

  4. P4169 [Violet]天使玩偶

    两种操作:1.加入点(x,y); 2.查询距(x,y)最近的点的曼哈顿距离距离 思路:绝对值拆开通常可以取max,不过这里直接分类讨论4种情况,我们发现如果找\(i\)点左下点\(j\)\((x_j& ...

  5. Redis分布式锁实现Redisson 15问

    大家好,我是三友. 在一个分布式系统中,由于涉及到多个实例同时对同一个资源加锁的问题,像传统的synchronized.ReentrantLock等单进程情况加锁的api就不再适用,需要使用分布式锁来 ...

  6. 『忘了再学』Shell基础 — 25、扩展正则表达式

    目录 1.扩展正则表达式说明 2.练习 (1)+和?练习 (2)|和()练习 3.注意(重点) 1.扩展正则表达式说明 熟悉正则表达式的童鞋应该很疑惑,在其他的语言中是没有扩展正则表达式说法的,在Sh ...

  7. Redis中的原子操作(2)-redis中使用Lua脚本保证命令原子性

    Redis 如何应对并发访问 使用 Lua 脚本 Redis 中如何使用 Lua 脚本 EVAL EVALSHA SCRIPT 命令 SCRIPT LOAD SCRIPT EXISTS SCRIPT ...

  8. 使用JavaCV实现读取视频信息及自动截取封面图

    概述 最近在对之前写的一个 Spring Boot 的视频网站项目做功能完善,需要利用 FFmpeg 实现读取视频信息和自动截图的功能,查阅资料后发现网上这部分的内容非常少,于是就有了这篇文章. 视频 ...

  9. Python数据分析--Numpy常用函数介绍(9)--Numpy中几中常见的图形

    在NumPy中,所有的标准三角函数如sin.cos.tan等均有对应的通用函数. 一.利萨茹曲线 (Lissajous curve)利萨茹曲线是一种很有趣的使用三角函数的方式(示波器上显示出利萨茹曲线 ...

  10. SAP Web Dynpro-集成消息

    您可以使用消息管理器将消息集成到消息日志中. 您可以使用Web Dynpro代码向导打开消息管理器. 您可以从工具栏中打开Web Dynpro代码向导. 当您的ABAP工作台处于更改模式或编辑视图或控 ...