TypeDB Forces 2023 (Div. 1 + Div. 2, Rated, Prizes!) A-E
A
题意
给一个正整数 \(n\) ,找到一组正整数 \(x,y \leq n\) ,满足 \(x^y \cdot y + y^x \cdot x = n\) 。
题解
知识点:数学。
尝试 \(x=1\) ,显然此时 \(2y = n\) ,如果 \(n\) 为偶数可以直接求得。
又左式无论 \(x,y\) 奇偶性结果都是偶数,因此 \(n\) 为奇数时无解。
时间复杂度 \(O(1)\)
空间复杂度 \(O(1)\)
代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
bool solve() {
int n;
cin >> n;
if (n & 1) return false;
else cout << 1 << ' ' << n / 2 << '\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;
}
B
题意
给定一个正整数 \(n\) ,将其分解为 \(\prod_{i=1}^m a_{i}^{p_{i}}\) ,其中 \(a_i\) 是不同素数的乘积。
问 \(\sum_{i=1}^m a_i \cdot p_i\) 的最大值。
题解
知识点:质因数分解,贪心。
先考虑将 \(n\) 质因数分解 \(\prod_{i=1}^m a_{i}^{p_{i}}\) ,其中 \(a_i\) 为素数。
显然,我们可以将不同的素数 \(a_i^{p_i},a_j^{p_j}\)合并成一个新的数 \((a_i \cdot a_j)^{\min(p_i,p_j)}\) ,这样的答案更优,因此我们考虑合并能合并不同的素数。
时间复杂度 \(O(\sqrt n)\)
空间复杂度 \(O(1)\)
代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void get_pfactor(int n, vector<pair<int, int>> &pfactor) {
for (int i = 2;i * i <= n;i++) {
if (!(n % i)) {
pfactor.push_back({ i,0 });
while (!(n % i)) n /= i, pfactor.back().second++;
}
}
if (n > 1) pfactor.push_back({ n,1 });//最后可能留一个大于sqrt(n)的质数
}
bool solve() {
int n;
cin >> n;
vector<pair<int, int>> pfactor;
get_pfactor(n, pfactor);
vector<ll> v(32, 1);
for (auto [x, y] : pfactor) v[y] *= x;
ll ans = 0;
for (int i = 30;i >= 1;i--) v[i] *= v[i + 1], ans += (v[i] > 1) * v[i];
cout << ans << '\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;
}
C
题意
给定一组数 \(a_i\) 和 \(s\) ,将 \(a_i,i \in [2,n-1]\) 分解为新的两个非负整数 \(x_i,y_i\) 且满足 \((x_i - s) \cdot (y_i - s) \geq 0\) 。
求 \(F = a_1 \cdot x_2 + y_2 \cdot x_3 + \cdots + y_{n-1} \cdot a_n\) 的最小值。
题解
知识点:线性dp,贪心。
对于 \(x_i,y_i\) 满足的不等式,可以理解为 \(x_i,y_i\) 要同时大于等于 \(s\) 或小于等于 \(s\) 。
考虑对 \(a_i\) 贪心地分解为一个最小值和一个最大值,即当 \(a_i \geq 2s\) ,可以分解为 \(x_i = s,y_i = a_i-s\) ;当 \(a_i < 2s\) ,可以分解为 \(x_i = \max(0,a_i-s),y_i = \min(s,a_i)\) 。可以如此证明,考虑某一段 \(y_{i-1} \cdot x_i+y_i\cdot x_{i+1} = (y_{i-1}-x_{i+1})\cdot x_i+a_i\cdot x_{i+1}\) ,无论 \(y_{i-1},x_{i+1}\) 如何, \(x_i\) 的极值点一定是在最小值或最大值处,而且这种选择没有后效性,因此分解只需要分解为一个最小值和一个最大值。
接下来我们需要确定最小值和最大值的顺序,考虑设 \(f_{i,0/1}\) 表示 \(a_1\cdot x_2 + \cdots+y_{i-1} \cdot x_i\) 中 \(x_i\) 是最小值/最大值时 \(F\) 的最小值,我们可以通过 \(f_{i-1,0/1}\) 来转移。
时间复杂度 \(O(n)\)
空间复杂度 \(O(n)\)
代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
bool solve() {
int n, s;
cin >> n >> s;
vector<pair<int, int>> p(n + 1);
for (int i = 1;i <= n;i++) {
int x;
cin >> x;
if (i == 1) p[1] = { 1e9,x };
else if (i == n) p[n] = { x,1e9 };
else {
if (x >= 2 * s) p[i] = { s,x - s };
else p[i] = { max(0,x - s),min(x,s) };
}
}
array<ll, 2> f{};
f[0] = f[1] = 0;
for (int i = 2;i <= n;i++) {
array<ll, 2> g{};
auto [x1, y1] = p[i - 1];
auto [x2, y2] = p[i];
g[0] = min(f[0] + 1LL * y1 * x2, f[1] + 1LL * x1 * x2);
g[1] = min(f[0] + 1LL * y1 * y2, f[1] + 1LL * x1 * y2);
f = g;
}
cout << f[0] << '\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;
}
D
题意
给定 \(n\) 个数 \(a_i\) ,从第 \(1\) 个数出发,每次可以跳到第 \(i+a_i\) 个数,直到跳到 \(<1\) 或 \(>n\) 的地方游戏结束。
现在可以选择一个数字改成 \([-n,n]\) 的任意一个数字,问有多少种改变方式(不改也算一种),能使得游戏结束。
题解
知识点:dfs,枚举。
我们可以把跳转路径画成一张有向图, \(0\) 作为游戏结束的点,那么 \(1\) 与 \(0\) 连通表示游戏一定可以结束。
考虑两类点:
- 从 \(1\) 出发能经过的点。
- 与 \(1\) 无关的其他点。
对于第二类点,改变他们并不影响 \(1\) 到终点的连通状态。因此,当 \(1\) 初始已经合法,那么他们能直接贡献 \(2n+1\) 个改变方案,否则没有任何贡献。
对于第一类点,我们需要注意,改变他们可能使得 \(1\) 无解或路径成环。除去 \(n+1\) 种直接导向 \(0\) 点的方案,他们只能连接那些能到达 \(0\) 且不会使路径成环的点。
对此,我们先给第一类点标记一个到 \(0\) 的距离(无穷大表示不可达)。第一类点可以导向距离比他小的第一类点,而反之一定成环。对于第二类点,如果他们能导向某个第一类点,那么我们可以认为他们的距离和这个第一类点是一样的,因为他们能不能使得路径成环,取决于他们导向的那个第一类点的距离大小,于是我们可以用相同的策略判断第二类点是否可以被导向。因此,我们把可达的点的距离排个序,每次可以二分查找得到合法点的个数
时间复杂度 \(O(n \log n)\)
空间复杂度 \(O(n)\)
代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int n;
int a[200007];
bool vis[200007], vis2[200007];
int dis[200007];
int dfs(int u) {
if (u < 1 || u > n) return 0;
if (vis[u]) return dis[u];
vis[u] = 1;
return dis[u] = dfs(u + a[u]) + 1;
}
int dfs2(int u) {
if (u < 1 || u > n) return 0;
if (vis[u] || vis2[u]) return dis[u];
vis2[u] = 1;
return dis[u] = dfs2(u + a[u]);
}
bool solve() {
cin >> n;
for (int i = 1;i <= n;i++) cin >> a[i], dis[i] = 1e9, vis[i] = vis2[i] = 0;
dfs(1);
for (int i = 1;i <= n;i++) dfs2(i);
vector<int> v;
for (int i = 1;i <= n;i++) if (dis[i] < 1e9) v.push_back(dis[i]);
sort(v.begin(), v.end());
ll ans = 0;
for (int i = 1;i <= n;i++) {
if (vis[i]) ans += n + 1 + (lower_bound(v.begin(), v.end(), dis[i]) - v.begin());
else if (dis[1] < 1e9) ans += 2 * n + 1;
}
cout << ans << '\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;
}
E
题意
给定正整数 \(n,k,x\) ,要求分为恰好 \(k\) 个非空子序列,使得这 \(k\) 个子序列的异或和都为 \(x\) 。
题解
知识点:位运算,贪心,构造。
容易知道,有解的必要条件是 \(k\) 个 \(x\) 的异或和等于 \(a_i\) 的异或和。满足必要条件后,我们尝试划分序列。
因为满足了必要条件,那我们如果能分出合法序列,那么序列个数的奇偶性一定和 \(k\) 相同,而其他数的异或和一定为 \(0\) 。
我们讨论合法序列个数的最大值情况:
最大值大于等于 \(k\) 一定有解,我们可以把多出来的序列和多余的数全部扔进一个序列里,不会改变异或和。
最大值小于 \(k\) 个一定无解,因为已经是能得到的最大值了。
于是问题变成如何分出最多的合法序列。我们可以通过这样的方法,在 \([1,n]\) 中:
- 如果有 \(x\) 那就单独分一组。
- 对于 \(i\) ,如果 \(x \oplus i \leq n\) ,那就 \(i, x \oplus i\) 两个数分一组。
这样就能得到最多的合法序列。
证明:
为了异或得到 \(x\) ,那么我们一定要保证每个序列都有奇数个数,满足在 \(x\) 的最高位 \(1\) 处也是 \(1\) 。
假设 \([1,n]\) 中有 \(m\) 个数满足在 \(x\) 的最高位 \(1\) 处也是 \(1\) ,那我们至多可以分 \(m\) 个序列。
对于 \(m\) 个数中任意一个数 \(i\) , \(i \oplus x\) 一定小于 \(i\) ,所以一定能找到数 \(i \oplus x\) 与其对应。同时,根据异或运算的等式性质,可以断定 \(i,i \oplus x\) 是唯一确定的一对,不会出现一个数被多个数对应,所以我们至少可以分 \(m\) 个序列。
因此我们一定能通过 \(i,i \oplus x\) ( \(x\) 可以直接安排进一个序列)的方式分出最多的序列,共 \(m\) 个。
得到最多的合法序列后,判断后即可构造或者无解。
时间复杂度 \(O(n)\)
空间复杂度 \(O(n)\)
代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
bool solve() {
int n, k, x;
cin >> n >> k >> x;
int xsum = 0;
for (int i = 1;i <= n;i++) xsum ^= i;
if (xsum != x * (k & 1)) return false;
vector<char> vis(n + 1);
vector<vector<int>> v;
for (int i = 1;i <= n;i++) {
if (vis[i] || (x ^ i) > n) continue;
if (i == x) v.push_back({ i });
else v.push_back({ i,x ^ i });
vis[i] = vis[i ^ x] = 1;
}
if (v.size() < k) return false;
cout << "YES" << '\n';
for (int i = 0;i < k - 1;i++) {
cout << v[i].size() << ' ';
for (auto val : v[i]) cout << val << ' ';
cout << '\n';
}
vector<int> r;
for (int i = k - 1;i < v.size();i++) for (auto val : v[i]) r.push_back(val);
for (int i = 1;i <= n;i++) if (!vis[i]) r.push_back(i);
cout << r.size() << ' ';
for (auto val : r) cout << val << ' ';
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 << "NO" << '\n';
}
return 0;
}
TypeDB Forces 2023 (Div. 1 + Div. 2, Rated, Prizes!) A-E的更多相关文章
- Codeforces 1023 A.Single Wildcard Pattern Matching-匹配字符 (Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Fi)
Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final) A. Single Wildcard Patter ...
- Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)-D. Restore Permutation-构造+树状数组
Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)-D. Restore Permutation-构造+树状数组 [Pro ...
- Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)-C. Magic Grid-构造
Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)-C. Magic Grid-构造 [Problem Descripti ...
- Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)-E. Let Them Slide-思维+数据结构
Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)-E. Let Them Slide-思维+数据结构 [Problem ...
- CF Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined)
1. Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) B. Batch Sort 暴力枚举,水 1.题意:n*m的数组, ...
- xHTML+div布局:三个div,两边div宽度固定,中间div宽度自适应
xHTML+div经常考题:三个div,两边div宽度固定,中间div宽度自适应. 和大家分享一个实现方式: 1.html代码 <div class="dyleft"> ...
- getElementsByTagName("div")和$("div")区别
作者:zccst <body> <div class="selected">1</div> <div class="select ...
- 【codeforces】【比赛题解】#868 CF Round #438 (Div.1+Div.2)
这次是Div.1+Div.2,所以有7题. 因为时间较早,而且正好赶上训练,所以机房开黑做. 然而我们都只做了3题.:(. 链接. [A]声控解锁 题意: Arkady的宠物狗Mu-mu有一只手机.它 ...
- Codeforces Round #438 (Div.1+Div.2) 总结
本来兴致勃勃的想乘着这一次上紫,于是很早很早的到了机房 但是好像并没有什么用,反而rating-=47 Codeforces Round #438(Div.1+Div.2) 今天就这样匆匆的总结一下, ...
- div覆盖div DIV相互重叠如何解决
div覆盖div,出现div与div盒子之间产生重叠覆盖现象,而内容没有出现覆盖重叠现象原因与解决方法.DIVCSS5通过CSS图文案例介绍产生原因与解决方法.DIV与DIV覆盖原因与解决方法. 可能 ...
随机推荐
- 云原生之旅 - 5)Kubernetes时代的包管理工具 Helm
前言 上一篇文章 [基础设施即代码 使用 Terraform 创建 Kubernetes] 教会了你如何在Cloud上面建Kubernetes资源,那么本篇来讲一下如何在Kubernetes上面部署应 ...
- Python基础之函数:2、globlal与nonlocal和闭包函数、装饰器、语法糖
目录 一.global与nonlocal 1.global 2.nonlocal 二.函数名的多种用法 三.闭包函数 1.什么是闭包函数 2.闭包函数需满足的条件 3.闭包函数的作用 4.闭包函数的实 ...
- ES6 学习笔记(十二)代理器Proxy的简单使用
1.前言 以前在学习react时做了个仿手机端的QQ音乐项目.当时的数据是通过proxy代理的QQ音乐数据接口,直接写在package.json里面.Proxy 对象(Proxy)是 ES6的特性,只 ...
- 嵌入式-Linux基础操作
Crtl+Alt+T:调出命令窗口 xrandr:列出分辨率列表 设置窗口的分辨率大小为1280x960:xrandr -s 1280x960 通过命令窗口来执行一段C语言程序: VI工具的使用: ( ...
- nacos的使用
一:下载nacos 打开github搜索nacos,选择历史版本,建议下载1.4版本的,较稳定 https://github.com/alibaba/nacos 二:下载完后解压文件,两种方式打开 1 ...
- 【DL论文精读笔记】VGGNet
VGGNet(Very Deep Convolutional Networks) 1.introduction ● 采用3x3的小卷积核应用在比较深的网络里 ● 结果不错,赢得了2014 Imagen ...
- CPU TLB原理 [转载好文]
首先,我们知道MMU的作用是把虚拟地址转换成物理地址.虚拟地址和物理地址的映射关系存储在页表中,而现在页表又是分级的.64位系统常见的配置是4级页表,就以4级页表为例说明.分别是PGD.PUD.PMD ...
- Devexpress中gridControl设置一列不可以编辑
gridView1.Columns["列名"].OptionsColumn.AllowEdit = false;//设置列不可以编辑 记录一下. 大家如果有问题可以 Consol ...
- nginx配置文件单独创建和管理
在nginx主配置文件nginx.conf的http模块下引入配置文件夹(注意路径的正确性) 1.nginx主配置文件备份后编辑(nginx配置存放位置:/usr/local/nginx/conf/) ...
- IOS移动端 -webkit-overflow-scrollin属性造成的问题
-webkit-overflow-scrolling带来的相关问题. -webkit-overflow-scrolling 属性控制元素在移动设备上是否使用滚动回弹效果. 其具有两个属性: auto: ...