Codeforces Round #696 (Div. 2) (A~C题解)
写在前边
A. Puzzle From the Future
链接:A题链接
题目大意:
给定一个,,,例如:, , ,但是d如果有连续重复的数字那么会省掉,假如,则,现在已知,丢失了,要求求出一个使得最大。
思路:
首先要使得最大化,的第一位必定是,剩下的直接从前到后模拟即可,若那么会减小,因此“反其道而行之即可”。
代码:
#include <iostream>
#include <string>
#include <algorithm>
#include <cstdio>
using namespace std;
#define Inf 0x3f3f3f3f
#define PII pair<int, int>
#define PLL pair<long, long>
typedef long long LL;
typedef unsigned long long ULL;
void solve() {
string s, res = "1";
int n;
cin >> n;
cin >> s;
for (int i = 1; i < s.size(); i++) {
if (((s[i]-'0') + 1) == (s[i - 1] - '0' + res[i - 1] - '0')) {
res += '0';
} else {
res += '1';
}
}
cout << res << endl;
}
int main()
{
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
B. Different Divisors
链接:B题链接
题目大意:
给定一个,求,要求至少有个约数,并且约数两两之间的至少差,并且要求是可行方案中中的最小值。
思路:
题目要求四个约数,那么让其只有四个约数即可,即,, ,因此就是大于的最小质数,就是大于的最小质数,那么就是满足条件。
证明:
若是一个合数,那么之间必定还会会有一个的约数,因为是的约数,那么它必然也是的约数这就使得,不满足约数之间至少差的条件,因此矛盾。
若不是最小质数,设其为,另一个为,那么,因此、并不是最优解。
综上:为的最小质数与为最小质数为最优解。
代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
#define Inf 0x3f3f3f3f
#define PII pair<int, int>
#define PLL pair<long, long>
typedef long long LL;
typedef unsigned long long ULL;
typedef vector<long long> VLL;
typedef vector<int> VI;
const int N = 25e3 + 10;
int primes[N], cnt;
bool st[N];
void get_primes() {
for (int i = 2; i <= N; i++) {
if (!st[i]) {
primes[cnt++] = i;
}
for (int j = 0; primes[j] <= N / i; j++) {
st[primes[j] * i] = true;
if (i % primes[j] == 0) {
break;
}
}
}
}
void solve() {
int d;
cin >> d;
int p, q, pcnt = 0;
for (pcnt; pcnt <= cnt; pcnt++) {
if (primes[pcnt] - 1 >= d) {
p = primes[pcnt];
break;
}
}
for (int i = pcnt; i <= cnt; i++) {
if (primes[i] - p >= d) {
q = primes[i];
break;
}
}
cout << p * q << endl;
}
int main()
{
int t;
cin >> t;
get_primes();
while (t--) {
solve();
}
return 0;
}
C. Array Destruction
链接:C题链接
题目大意:
例如,如果最初,则可以选择。然后你可以选择第二个和第三个元素的总和,并抛出它们。在这个运算之后,等于,数组中有两个元素:和。你可以在下次操作时把它们扔了,那么输出
YES
6
1 5
2 3
若无论如何数组内元素都无法清空,那么输出即可。
思路:
每次选最大的数作为x。
证明:
假设,不选来构造x,那么即,此后,之后无论如何都消除不掉,因此每次选最大数作为x即可。
那么第一次除了选最大的数作为下一轮的x,另一个数就需要枚举所有可能,直到枚举到一个可以消掉所有数的情况。明白了这一点那么剩下的只需要模拟即可,可以用,因为其查找删除插入操作都是,若不用则手写二分查找即可,最时间复杂度:
自己的错误:写了一晚上,但最后还是告终,其实我已经知道了每次要选最大值了,但还是用双指针来搜哪两个数等于,由于答案唯一,因此搜的结果是对的,但是导致被卡,应该直接确定数组中还剩下的最大数,然后剩下的小数直接用二分搜就好了。
代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <set>
using namespace std;
#define Inf 0x3f3f3f3f
#define PII pair<int, int>
#define PLL pair<long, long>
typedef long long LL;
typedef unsigned long long ULL;
typedef vector<long long> VLL;
typedef vector<int> VI;
vector<PII> check(VI all, int n, int x) {
vector<PII> res;
multiset<int> s;
for (auto it : all) {
s.insert(it);
}
for (int i = 0; i < n; i++) { //2*n个数,n个答案
auto it1 = s.end();
it1--;
int y = x - *it1;
s.erase(it1);
auto it2 = s.find(y);
if (it2 == s.end()) {
return {};
}
s.erase(it2);
res.push_back({y, x - y});
x = max(x - y, y);
}
return res;
}
void solve() {
int n;
cin >> n;
VI all;
for (int i = 0; i < n * 2; i++) {
int c;
cin >> c;
all.push_back(c);
}
sort(all.begin(), all.end());
for (int i = 0; i < all.size() - 1; i++) { //枚举第一次操作的第二个数
int x = all[i] + all[all.size() - 1]; //最大的一个
vector<PII> res = check(all, n, x);
if (res.size()) {
cout << "YES" << endl;
cout << x << endl;
for (auto it : res) {
cout << it.first << " " << it.second << endl;
}
return;
}
}
cout << "NO" << endl;
}
int main()
{
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端