比赛链接

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. 搞定了!OAuth2使用验证码进行授权

    现在验证码登录已经成为很多应用的主流登录方式,但是对于OAuth2授权来说,手机号验证码处理用户认证就非常繁琐,很多同学却不知道怎么接入. 认真研究胖哥Spring Security OAuth2专栏 ...

  2. Hadoop安装学习(第二天)

    学习任务: 1.对VMnet8进行设置 2.配置主机名,对host文件进行编辑 3.将Hadoop文件以及jdk通过Xshell7传输到Linux系统 4.设置免密登录

  3. Object类和对象类型转换

    学习内容:Object类和对象类型转换 一.Object类 1.Object类是所有类的父类,是Java类层中最高层的类. 2.getClass()方法:返回对象执行时的Class实例,然后用此实例调 ...

  4. Vue2框架

    Vue2框架 Vue定义 Vue.js是一种构建用户界面的渐进式框架,提供了MVVM模型数据绑定和一个可组合的组件系统,具有简单灵活的API,采用自底向上逐层应用 Vue安装 / 浏览器安装Vue D ...

  5. application.properties文件中暗藏玄机

    上次分享了如何一步一步搭建一个springboot的项目,详细参见<5分钟快速搭建一个springboot的项目>,最终的结果是在"8080"端口搭建起了服务,并成功访 ...

  6. java继承中关于super关键字和this关键字的使用

    1.super关键字 由于子类不能继承父类的构造方法,因此,如果要调用父类的构造方法,可以使用 super 关键字.super 可以用来访问父类的构造方法.普通方法和属性.super 关键字的功能: ...

  7. Redis的使用(二)

    一.redis简单应用 其实在写这个redis专题时我想了很久,我觉得redis没什么好说的,因为现在是个人都会用redis,但是我在写netty专题时发现,netty里面很多东西和概念有很多跟red ...

  8. 倾斜摄影3D模型|手工建模|BIM模型 轻量化处理

    一.什么是大场景? 顾名思义,大场景就是能够从一个鸟瞰的角度看到一个大型场景的全貌,比如一个园区.一座城市.一个国家甚至是整个地球.但过去都以图片记录下大场景,如今我们可以通过建造3D模型来还原大场景 ...

  9. BUUCTF-[BJDCTF2020]认真你就输了

    [BJDCTF2020]认真你就输了 下载通过16进制查看发现是压缩包,直接就binwalk分离查看. 分离直接得到几个文件,不过好像压缩包里的和外面的文件是一样的,所以直接翻一下目录 直接就找到了 ...

  10. 数学公式 Latex 练习

    \[1+x+x^2+x^3+\cdots=\frac{1}{1-x}\quad x\in(-1, 1) \] 证明:设左边式子项数为 \(n\) 那么可以得到: \[\begin{split} S & ...