A
题意
需要检查一个包含3个整数的数组,是否存在两个数之和大于等于10。
题解
主要思路是:
- 计算数组所有元素之和sum
- 遍历数组,检查sum减去当前元素是否>= 10
- 如果找到满足的元素,设置found=true,退出循环
- 根据found的值输出结果
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int T;
cin >> T;
while(T--) {
int a[3];
for(int i = 0; i < 3; i++) {
cin >> a[i];
}
bool found = false;
int sum = accumulate(a, a + 3, 0);
for(int i = 0; i < 3; i++) {
if(sum - a[i] >= 10) {
found = true;
break;
}
}
if(found) {
cout << "YES" << endl;
}
else {
cout << "NO" << endl;
}
}
return 0;
}
B
题意
给出若干个(a, b)对,找出a<=10中b最大的下标
题解
- 读入测试用例的个数T,对每个测试用例循环
- 读入对的个数n,创建一个元组(a, b, i)的向量,其中i是对的下标
- 使用std::partition将向量分成两部分:第一部分包含所有a<=10的元组,第二部分包含剩余的元组
- 使用std::max_element在第一部分的向量中找到b最大的元组
- 输出找到的元组的下标i加一(因为题目中的下标是从1开始的)
代码
#include <bits/stdc++.h>
typedef std::pair<int, int> pii;
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
int T;
std::cin >> T;
while (T--)
{
int n;
std::cin >> n;
std::vector<std::tuple<int, int, int>> a(n);
int length, quality;
for (int i = 0; i < n; i++) {
std::cin >> length >> quality;
a[i] = std::make_tuple(length, quality, i);
}
auto iter = std::partition(a.begin(), a.end(), [](auto it)
{ return std::get<0>(it) <= 10; });
auto max_iter = std::max_element(a.begin(), iter, [&](const auto &a, const auto &b)
{ return std::get<1>(a) < std::get<1>(b); });
std::cout << std::get<2>(*max_iter) + 1 << '\n';
}
}
C
题意
在 8*8 的字符矩阵中有一列中存在连续小写字母存在的单词,其余皆为 *,找出其中的单词
题解
- 读入8个字符串,表示矩阵的每一行,存储在一个向量中
- 初始化一个空字符串res,用来存储结果
- 遍历向量中的每个字符串和每个字符
- 如果字符是小写字母,就把它加到res后面
- 输出res作为答案
代码
#include <bits/stdc++.h>
typedef std::pair<int, int> pii;
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
int T;
std::cin >> T;
while (T--)
{
std::vector<std::string> s(8);
for (auto &it : s)
std::cin >> it;
std::string res;
for (auto str : s)
for (char ch : str)
if(islower(ch))
res.push_back(ch);
std::cout << res << '\n';
}
}
D
题意
移除尽量少的元素使得数列中所有连续的元素之差小于等于 k
题解
- 首先,对输入的数列进行排序,使得相邻的元素之差最小。
- 然后,用一个双指针法遍历数列,找出最长的连续子序列,使得其中任意两个元素之差不超过k。
- 最后,用数列的长度减去最长子序列的长度,就是需要移除的元素个数。
代码
#include <bits/stdc++.h>
typedef std::pair<int, int> pii;
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
int T;
std::cin >> T;
while (T--)
{
int n, k;
std::cin >> n >> k;
std::vector<int> a(n);
for (auto &it : a)
std::cin >> it;
sort(a.begin(), a.end());
int res = INT_MIN;
for (int j = 0; j < n;)
{
int p = j;
while (++j < n && a[j] - a[j - 1] <= k)
;
res = std::max(res, j - p);
}
std::cout << n - res << '\n';
}
}
E
题意
将 n 个边长为 a_i 的正方形,给每个正方形边长增加到 a_i + 2*w,使得所有正方形面积之和小于等于 c
题解
- 使用二分查找法来找出最大的满足条件的w值,即所有正方形的面积之和不超过c。
- 定义一个check函数来判断给定的w值是否满足条件,即计算所有正方形的新面积之和,并与c进行比较。
- 在主函数中,对数列进行排序,并初始化二分查找的左右边界和答案。
- 在二分查找的过程中,每次取中间值作为w值,并调用check函数来判断是否满足条件,根据结果更新左右边界和答案。
代码
#include <bits/stdc++.h>
typedef std::pair<int, int> pii;
typedef long long LL;
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
int T;
std::cin >> T;
while (T--)
{
int n;
LL s;
std::cin >> n >> s;
std::vector<LL> a(n);
for (auto &it : a)
std::cin >> it;
int left = 1, right = 1e9 / 2, mid, ans;
auto check = [&](LL mid) -> bool
{
LL res = 0;
mid <<= 1;
for (auto it : a)
{
res += (mid + it) * (mid + it);
if (res > s)
return false;
}
return true;
};
while (left <= right)
{
mid = (left + right) >> 1;
if (check(mid))
{
left = mid + 1;
ans = mid;
}
else
right = mid - 1;
}
std::cout << ans << '\n';
}
}
F
题意
有 n 只青蛙,每只青蛙以 a_i 为步长不停得跳,在 [1, n] 中设置一个陷阱,捕捉尽可能多得青蛙,问做多能抓几只青蛙
题解
- 首先,观察到如果青蛙的步长为 a,那么它只能跳到 a 的倍数的位置,所以我们可以按照步长来分组,统计每个步长有多少只青蛙。
- 然后,对于每个位置 i,我们可以遍历它的所有因子 j,并累加对应步长为 j 的青蛙的数量,得到在位置 i 可以捕捉到的青蛙的总数。
- 最后,我们在所有位置中找出最大的青蛙数量,就是答案。
复杂度为[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iUrS9HAN-1690212116810)(https://cdn.nlark.com/yuque/__latex/e45d75731139a9fda4a629426bf1f9ac.svg#card=math&code=n%2Alog%28n%29&id=Y0WpK)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y9BuBzYY-1690212116812)(https://cdn.nlark.com/yuque/__latex/1628a4ea7644802f0675c699b8e8320e.svg#card=math&code=%5Cfrac%7Bn%7D%7B1%7D%2B%5Cfrac%7Bn%7D%7B2%7D%2B%5Ccdots%2B%5Cfrac%7Bn%7D%7Bn%7D&id=EnBuL)] 这是著名的调和级数等于 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zoWblqHE-1690212116813)(https://cdn.nlark.com/yuque/__latex/dfbe0f7fcfb94e894b5c8502532f2797.svg#card=math&code=n%2Aln%28n%29&id=rscJV)]
代码
#include <bits/stdc++.h>
typedef std::pair<int, int> pii;
typedef long long LL;
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
int T;
std::cin >> T;
while (T--)
{
int n, x;
std::cin >> n;
std::vector<int> a(n + 1), c(n + 1);
for (int i = 1; i <= n; i++)
{
std::cin >> x;
if (x <= n)
a[x]++;
}
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j += i)
c[j] += a[i];
std::cout << *std::max_element(c.begin(), c.end()) << '\n';
}
}
G
题意
有 n 个二维点,问有几个二维点对,连成的线为8个方向之一
题解
- 首先,观察到如果两个点连成的线为8个方向之一,那么它们必须满足以下四种情况之一:
- 它们的横坐标相同,也就是说,它们在同一条竖直线上。
- 它们的纵坐标相同,也就是说,它们在同一条水平线上。
- 它们的横坐标和纵坐标之和相同,也就是说,它们在同一条从左下到右上的对角线上。
- 它们的纵坐标减去横坐标之差相同,也就是说,它们在同一条从左上到右下的对角线上。
- 然后,我们可以用四个数组来分别存储每个点的横坐标、纵坐标、横纵坐标之和、横纵坐标之差,并对每个数组进行排序。
- 接着,我们可以用一个函数来计算每个数组中有多少对相同的元素,也就是说,有多少对点满足其中一种情况。这个函数的思路是:
- 遍历数组中的每个元素,并用一个变量来记录当前元素出现的次数。
- 如果遇到不同的元素,就计算当前元素出现次数的二项式系数,也就是从中选两个的组合数,并累加到结果中。
- 如果遍历到数组的末尾,也要计算最后一个元素出现次数的二项式系数,并累加到结果中。
- 最后,我们把四个数组分别调用这个函数得到的结果相加,就是答案。
代码
#include <bits/stdc++.h>
typedef std::pair<int, int> pii;
typedef long long LL;
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
int T;
std::cin >> T;
while (T--)
{
auto cal = [](std::vector<int> vec) -> LL
{
std::sort(vec.begin(), vec.end());
int n = (int)vec.size();
LL res = 0;
for (int j = 0; j < n;)
{
int p = j;
while (++j < n && vec[j] == vec[j - 1])
;
LL len = j - p;
res += len * (len - 1);
}
return res;
};
int n;
std::cin >> n;
std::vector<pii> points(n);
for (auto &point : points)
std::cin >> point.first >> point.second;
std::vector<int> x, y, xplusy, ysubx;
std::transform(points.begin(), points.end(), std::back_inserter(x), [](const pii &point)
{ return point.first; });
std::transform(points.begin(), points.end(), std::back_inserter(y), [](const pii &point)
{ return point.second; });
std::transform(points.begin(), points.end(), std::back_inserter(xplusy), [](const pii &point)
{ return point.first + point.second; });
std::transform(points.begin(), points.end(), std::back_inserter(ysubx), [](const pii &point)
{ return point.second - point.first; });
LL res = cal(x) + cal(y) + cal(xplusy) + cal(ysubx);
std::cout << res << '\n';
}
}
H
题意
已知 n 个横坐标轴上点 a_i,和 m 个约束
每个约束 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UWSk2lAa-1690212116814)(https://cdn.nlark.com/yuque/__latex/6dc3974d55cff8726ef9c61a7a825894.svg#card=math&code=a_x%20-%20a_y%20%3D%20d&id=KU9og)], 问是否存在 n 个点满足所有约束
题解
- 首先,把每个约束看作一条有向边,从点 x 指向点 y,边的权值为 d,表示 a_x - a_y = d。这样就可以把问题转化为一个图论问题,即判断这个图是否存在环,并且环上的边权之和是否为0。
- 然后,我们可以用一个深度优先搜索(DFS)算法来遍历这个图,同时记录每个点的距离(即 a_i 的值),并检查是否有矛盾的情况出现。具体地,我们可以用一个数组 vis 来标记每个点是否被访问过,用一个数组 dis 来存储每个点的距离,用一个函数 dfs 来实现DFS算法。
代码
#include <bits/stdc++.h>
typedef std::pair<int, int> pii;
typedef long long LL;
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
int T;
std::cin >> T;
while (T--)
{
int n, m;
std::cin >> n >> m;
std::vector<std::vector<pii>> E(n + 1);
for (int i = 1; i <= m; i++)
{
int u, v, d;
std::cin >> u >> v >> d;
E[u].push_back(std::make_pair(v, d));
E[v].push_back(std::make_pair(u, -d));
}
bool flag = true;
std::vector<bool> vis(n + 1);
std::vector<LL> dis(n + 1);
std::function<void(int, LL)> dfs;
dfs = [&](int now, LL w)
{
vis[now] = true;
dis[now] = w;
for (auto item : E[now])
{
int &v = item.first;
int &d = item.second;
if (!vis[v])
dfs(v, w + d);
else
{
if (dis[v] - dis[now] != d)
flag = false;
}
}
};
for (int i = 1; i <= n; i++)
if (!vis[i])
dfs(i, 0);
std::cout << (flag ? "YES\n" : "NO\n");
}
}