2024-2025 ICPC, NERC, Southern and Volga Russian Regional Contest 个人题解(A,B,C,G,J,K,L,N)
2024-2025 ICPC, NERC, Southern and Volga Russian Regional Contest 个人题解(A,B,C,G,J,K,L,N)
Dashboard - 2024-2025 ICPC, NERC, Southern and Volga Russian Regional Contest (Unrated, Online Mirror, ICPC Rules, Preferably Teams) - Codeforces
难度排序
由低到高
N、J、L、C、A、G、K、B。
火车头
#include <bits/stdc++.h>
using namespace std;
#define ft first
#define sd second
#define yes cout << "yes\n"
#define no cout << "no\n"
#define Yes cout << "Yes\n"
#define No cout << "No\n"
#define YES cout << "YES\n"
#define NO cout << "NO\n"
#define pb push_back
#define eb emplace_back
#define all(x) x.begin(), x.end()
#define all1(x) x.begin() + 1, x.end()
#define unq_all(x) x.erase(unique(all(x)), x.end())
#define unq_all1(x) x.erase(unique(all1(x)), x.end())
#define inf 0x3f3f3f3f
#define infll 0x3f3f3f3f3f3f3f3fLL
#define RED cout << "\033[91m" // 红色
#define GREEN cout << "\033[92m" // 绿色
#define YELLOW cout << "\033[93m" // 蓝色
#define BLUE cout << "\033[94m" // 品红
#define MAGENTA cout << "\033[95m" // 青色
#define CYAN cout << "\033[96m" // 青色
#define RESET cout << "\033[0m" // 重置
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
// typedef __int128_t i128;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef pair<string, ll> psl;
typedef tuple<int, int, int> ti3;
typedef tuple<ll, ll, ll> tl3;
typedef tuple<ld, ld, ld> tld3;
typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<string> vs;
typedef vector<vi> vvi;
typedef vector<vl> vvl;
// std::mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());
template <typename T>
inline T read()
{
T x = 0;
int y = 1;
char ch = getchar();
while (ch > '9' || ch < '0')
{
if (ch == '-')
y = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = (x << 3) + (x << 1) + (ch ^ 48);
ch = getchar();
}
return x * y;
}
template <typename T>
inline void write(T x)
{
if (x < 0)
{
putchar('-');
x = -x;
}
if (x >= 10)
{
write(x / 10);
}
putchar(x % 10 + '0');
}
/*#####################################BEGIN#####################################*/
void solve()
{
}
int main()
{
ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
// freopen("test.in", "r", stdin);
// freopen("test.out", "w", stdout);
int _ = 1;
std::cin >> _;
while (_--)
{
solve();
}
return 0;
}
/*######################################END######################################*/
// 链接:
A. Bonus Project
有一个由 \(n\) 名软件工程师组成的团队,编号从 1 到 \(n\)。他们的老板承诺,如果他们完成一个额外的项目,就会给他们发奖金。该项目总共需要 \(k\) 个工作单位。答应给第 \(i\) 位工程师的奖金是 \(a_i\) 布勒斯。老板没有给工程师分配具体任务,而是希望每个工程师都能自愿完成某个整数的工作单位。只有当项目完成时,整个团队才会获得奖金;换句话说,如果项目中自愿完成的工作单位总数大于或等于 \(k\),整个团队才会获得奖金。
每位工程师可完成的工作量不受限制。不过,所有工程师都会珍惜自己的劳动成果。第 \(i\) 位工程师估计他们的一个工作单位为 \(b_i\) 布尔。如果支付了奖金,那么第 \(i\) 位工程师完成 \(c\) 个单位的工作所获得的收益 \(s_i\) 定义为 \(s_i = a_i - c \cdot b_i\)。如果不支付奖金,工程师将不会自愿完成任何工作。
工程师们在一起工作多年,因此他们知道奖金将如何分配以及同事们对劳动的重视程度。也就是说,团队中的每个工程师都知道所有的 \(a_i\) 和所有的 \(b_i\)。
工程师们都渴望获得奖金,因此他们之间商定了以下工作分配流程:
第一位工程师说:"我将完成 \(c_1\) 个工作单位",其中 \(c_1\) 是一个非负整数;
然后,第二个工程师说:"我将完成 \(c_2\) 个工作单位",其中 \(c_2\) 是一个非负整数;
......依此类推;
最后,第 \(n\) 位工程师说:"我将完成 \(c_n\) 个工作单位",其中 \(c_n\) 是一个非负整数。
每个工程师都会发出 \(c_i\) 的声音,使自己的利益 \(s_i\) 最大化。如果预期收益为零,工程师仍会同意工作以获得经验,并帮助同事获得奖金。但是,如果由于某种原因预期收益为负(工程师需要完成过多的工作或项目无法完成),该工程师将根本不工作(完成零工作量)。
鉴于每个工程师的行为都是完美的,你的任务是找出每个工程师所表达的数字 \(c_i\)。
输入
第一行包含两个整数 \(n\) 和 \(k\) ( \(1 \leq n \leq 1000\) ; \(1 \leq k \leq 10^6\) )——分别是公司的工程师人数和项目所需的工作单位数量。
第二行包含 \(n\) 个整数 \(a_1, a_2, \ldots, a_n\) ( \(1 \leq a_i \leq 10^9\) ),其中 \(a_i\) 是项目完成后将支付给第 \(i\) 个工程师的奖金。
第三行包含 \(n\) 个整数 \(b_1, b_2, \ldots, b_n\) ( \(1 \leq b_i \leq 1000\) ),其中 \(b_i\) 是第 \(i\) 位工程师的工作单位成本。
输出
打印 \(n\) 个整数 \(c_1, c_2, \ldots, c_n\) ( \(0 \leq c_i \leq k\) )——在每个工程师都表现最优的情况下,每个工程师完成的工作量。请注意,答案是唯一的。
示例
输入
3 6
4 7 6
1 2 3
输出
1 3 2
输入
3 12
4 7 6
1 2 3
输出
0 0 0
输入
3 11
6 7 8
1 2 3
输出
6 3 2
提示
在第一个示例中,工程师们在他们之间分配了工作并获得了奖金,尽管第三位工程师的收益为零。
在第二个示例中,奖金项目需要的工作单位太多,因此工程师们不工作更有利。
解题思路
由于工作分配流程是从前往后的,因此越后面的人,选择权越小。
倒着枚举,将工作尽可能分配给后面的人即可。
搞不定数据范围设置成1000干啥,吓人吗
实现代码
void solve()
{
int n, k;
cin >> n >> k;
vi a(n), b(n);
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
for (int i = 0; i < n; i++)
{
cin >> b[i];
}
vi ans(n);
int now = 0;
for (int i = n - 1; i >= 0; i--)
{
int num = a[i] / b[i];
num = min(num, k - now);
ans[i] = num;
now += num;
if (now == k)
break;
}
if (now < k)
{
for (int i = 0; i < n; i++)
{
cout << "0 ";
}
cout << "\n";
}
else
{
for (int i = 0; i < n; i++)
{
cout << ans[i] << " \n"[i == n - 1];
}
}
}
B. Make It Equal
给你一个大小为 \(n\) 的整数数组 \(a\)。数组元素的编号从 1 到 \(n\)。
您可以执行以下任意次数的操作(可能为 0 次):从 1 到 \(n\) 之间选择一个索引 \(i\);将 \(a_i\) 减少 2,并将 \(a_{(i \mod n) + 1}\) 增加 1。
执行这些操作后,数组中的所有元素都应是非负等整数。
你的任务是计算最少需要执行的运算次数。
输入
第一行包含一个整数 \(t\) ( \(1 \leq t \leq 10^4\) )——测试用例数。
每个测试用例的第一行包含一个整数 \(n\) ( \(2 \leq n \leq 2 \cdot 10^5\) )。
每个测试用例的第二行包含 \(n\) 个整数 \(a_1, a_2, \ldots, a_n\) ( \(1 \leq a_i \leq 10^9\) )。
输入的附加限制:所有测试用例中 \(n\) 的总和不超过 \(2 \cdot 10^5\)。
输出
对于每个测试用例,打印一个整数——你必须执行的最小操作数。如果不可能使数组中的所有元素都相等,则打印 -1。
示例
输入
3
2
1 1
3
1 3 2
4
2 1 2 6
输出
0
-1
3
解题思路
观察发现,如果一个数组全部元素相等,那么我们可以对所有元素进行一次操作,从而让所有元素都减 \(1\) 。
因此,如果一个数组能够通过操作使得数组元素全部相等,且使得相等的最大元素为 \(x\) 那么,我们一定也可以构造出 \([1,x-1]\) 相等的数组。
因此,最后的相等元素 \(x\) 具有二段性,所以我们可以二分 \(x\) 是否为最大的最终相等元素。
考虑设计检查函数。
我们可以对所有数进行操作,使得 $\forall a_i \le x $,然后检查是否 $\forall a_i = a_{i+1} $。
对于一个数 \(a_i\) 要把它变为 \(x\) ,当 \(a_i \le x\) 肯定是不操作;当 \(a_i>x\) 时,如果 \(a_i-x\) 为奇数,就先对 \(a_{i-1}\) 操作一次,让其变成偶数,然后对其操作 \(\frac{a_{i}-x}{2}\) 次。
如果只操作一遍,也许任然存在 \(a_i\gt x\) ,因此我们需要循环操作 直到$\forall a_i \le x $。
看上去可能超时,考虑极限情况 \(x=0,\forall a_i=10^9\)。
由于我们设计的操作函数每次会将 \(a_i\) 的值减半加到 \(a_{i+1}\) ,因此对于整体而言,我们每次都减去了 \(\frac{a_i}{2}\) ,极限情况下数组和为 \(n\times a_i\) ,因此我们总共会操作 \(log_2{a_i}\times n\) 。因此,我们检查函数的时间复杂度为 \(O(nlogV)\) 。
实现代码
void solve()
{
int n;
cin >> n;
vi a(n);
ll sum = 0;
for (int i = 0; i < n; i++)
{
cin >> a[i];
sum += a[i];
}
auto check = [&](int x) -> bool
{
vi temp = a;
while (1)
{
bool flag = true;
for (int i = 0; i < n; i++)
{
if (temp[i] <= x)
continue;
flag = false;
if ((temp[i] - x) & 1)
{
temp[(i - 1 + n) % n] -= 2;
temp[i]++;
}
temp[(i + 1) % n] += (temp[i] - x) / 2;
temp[i] = x;
}
if (flag)
break;
}
for (int i = 0; i < n; i++)
{
if (temp[i] != x)
return false;
}
return true;
};
int l = 0, r = (sum + n - 1) / n;
while (l < r)
{
int mid = (l + r + 1) >> 1;
if (check(mid))
l = mid;
else
r = mid - 1;
}
if (check(r))
cout << sum - 1ll * r * n << "\n";
else
cout << "-1\n";
}
C. DIY
给你一个由 \(n\) 个整数 \(a_1, a_2, \ldots, a_n\) 组成的列表。你需要从列表中选取 8 个元素作为四个点的坐标。这四个点应该是边平行于坐标轴的矩形的角。您的任务是选取坐标,使得到的矩形具有尽可能大的面积。矩形可以是退化矩形,即其面积可以是 0。每个整数在列表中出现的次数不限(或更少)。
输入
第一行包含一个整数 \(t\) ( \(1 \leq t \leq 25000\) )——测试用例数。
每个测试用例的第一行包含一个整数 \(n\) ( \(8 \leq n \leq 2 \cdot 10^5\) )。
每个测试用例的第二行包含 \(n\) 个整数 \(a_1, a_2, \ldots, a_n\) ( \(-10^9 \leq a_i \leq 10^9\) )。
输入的附加限制:所有测试用例中 \(n\) 的总和不超过 \(2 \cdot 10^5\)。
输出
对于每个测试用例,打印答案如下:
如果不可能构造出符合语句限制条件的矩形,则打印包含 NO(不区分大小写)字样的一行;
否则,在第一行打印 YES(不区分大小写)。在第二行中,打印 8 个整数 \(x_1, y_1, x_2, y_2, x_3, y_3, x_4, y_4\)——矩形各角的坐标。您可以按照任意顺序打印角的坐标。
示例
输入
3
16
-5 1 1 2 2 3 3 4 4 5 5 6 6 7 7 10
8
0 0 -1 2 2 1 1 3
8
0 0 0 0 0 5 0 5
输出
YES
1 2 1 7 6 2 6 7
NO
YES
0 0 0 5 0 0 0 5
解题思路
对于是否可以构建出矩阵,我们只需要检查是否存在 \(4\) 对以上相同的数即可。
对于如何找寻最大矩形,如果所以数的数量都大于 \(4\) ,那么我们一定是贪心的选择最大和最小的数作为矩形的边角,由此推得,我们一定是选择最大和次大,最小和次小的数对来构造矩形。
实现代码
void solve()
{
int n;
cin >> n;
map<int, int> mp;
for (int i = 0; i < n; i++)
{
int x;
cin >> x;
mp[x]++;
}
int cnt = 0;
for (auto x : mp)
{
cnt += x.sd / 2;
}
if (cnt < 4)
{
NO;
return;
}
int mx1 = -inf;
int mx2 = -inf;
int mn1 = inf;
int mn2 = inf;
for (auto x : mp)
{
if (x.sd >= 4)
{
mx1 = max(mx1, x.ft);
mx2 = max(mx2, x.ft);
mn1 = min(mn1, x.ft);
mn2 = min(mn2, x.ft);
}
else if (x.sd >= 2)
{
if (x.ft > mx1)
{
mx2 = mx1;
mx1 = x.ft;
}
else if (x.ft > mx2)
{
mx2 = x.ft;
}
if (x.ft < mn1)
{
mn2 = mn1;
mn1 = x.ft;
}
else if (x.ft < mn2)
{
mn2 = x.ft;
}
}
}
YES;
cout << mn1 << " " << mn2 << " " << mn1 << " " << mx1 << " " << mx2 << " " << mn2 << " " << mx2 << " " << mx1 << "\n";
}
G. Guess One Character
这是一个交互式问题。您必须在打印完每一行后立即使用 flush 操作。例如,在 C++ 中应使用函数 fflush(stdout) 或 cout.flush(),在 Java 或 Kotlin 中应使用 System.out.flush(),在 Python 中应使用 sys.stdout.flush()。
陪审团有一个由字符 0 和/或 1 组成的字符串 \(s\)。该字符串的长度为 \(n\)。
您可以进行以下查询:
- \(t\) — " \(t\) 作为连续子串在 \(s\) 中出现了多少次?" 在这里, \(t\) 应该是一个由字符 0 和/或 1 组成的字符串;其长度至少为 1 ,最多为 \(n\)。例如,如果字符串 \(s\) 是 111011,而字符串 \(t\) 是 11,那么查询的回复就是 3。
您必须通过不超过 3 的查询猜出字符串 \(s\) 中的至少一个字符。需要注意的是,给出答案并不算一次询问。
在每个测试和每个测试用例中,字符串 \(s\) 都是事先固定的。
互动
最初,陪审团程序发送一个整数 \(t\) ( \(1 \leq t \leq 1000\) )——测试用例数。
在每个测试用例开始时,陪审团程序发送一个整数 \(n\) ( \(2 \leq n \leq 50\) )——字符串的长度。
之后,您的程序可以通过打印以下一行向陪审团程序提交查询(打印完一行后不要忘记刷新输出!):
1 \(t\) 表示询问 " \(s\) 中的连续子串 \(t\) 出现了多少次?"
对于每个查询,陪审团都会在单独一行中打印一个整数。它要么是查询的答案,如果查询是正确的,并且没有超出查询限制;或者是整数 −1 ,如果您的查询不正确(例如,未满足约束 \(1 \leq |t| \leq n\) 或字符串 \(t\) 包含 0 和 1 以外的字符),或者您在处理当前测试用例时提出了太多查询。
要提交答案,您的程序应按以下格式发送一行(打印完一行后不要忘记刷新输出!):
0 \(i\) \(c\),其中 \(1 \leq i \leq n\) 和 \(c\) 要么为 0 要么为 1,即 \(s_i = c\)。
如果您的猜测正确,陪审团程序将在单独一行中打印一个整数 1 ,表示您可以进入下一个测试用例(如果是最后一个测试用例,则终止程序),并且您提出的询问次数将被重置。如果不正确,陪审团程序将在另一行打印一个整数 −1 。
程序收到 −1 作为响应后,应立即终止。这将导致您的提交收到 "错误答案" 的裁决。如果您的程序没有终止,则您的提交结果为 "未定义"。
示例
输入
3 // 3 测试用例
3 // 字符串长度为 3
1 // 101 出现一次
1 // 猜测正确
2 // 字符串长度为 2
0 // 00 出现零次
0 // 0 出现零次
1 // 猜测正确
2 // 字符串长度为 2
1 // 1 出现一次
0 // 01 出现零次
1 // 猜测正确
输出
1 101 // 查询 101 出现多少次
0 2 0 // 猜测:s[2] 是 0
1 00 // 查询 00 出现多少次
1 0 // 查询 0 出现多少次
0 1 1 // 猜测:s[1] 是 1
1 1 // 查询 1 出现多少次
1 01 // 查询 01 出现多少次
0 2 0 // 猜测:s[2] 是 0
注意
在示例中,有 3 个测试用例:101、11 和 10。请注意,所有注释内容(// 后的内容)不会在实际问题中打印,您也不应打印这些内容。空行也是为了方便您而添加的,陪审团程序不会打印它们,您的解决方案也不应打印任何空行。
解题思路
将字符除串按长度为 \(1\) 进行划分,我们可以得到 \(0\) 和 \(1\) 两种子字符串,按长度为 \(2\) 进行划分,我们可以得到 \(00\) , \(01\) , \(11\) 和 \(10\) 四种子字符串。
观察发现,如果只存在 \(00\) 和 \(01\) 字符串,那么 \(0\) 子字符串的数量将等于这两种字符串数量相加,那么最后一为一定是 \(1\) 。
实现代码
int query(string s)
{
printf("1 %s\n", s.c_str());
fflush(stdout);
return read<int>();
}
void answer(int pos, char c)
{
printf("0 %d %c\n", pos, c);
fflush(stdout);
}
void solve()
{
int n = read<int>();
int n0 = query("0");
int n00 = query("00");
int n01 = query("01");
if (n00 + n01 == n0)
answer(n, '1');
else
answer(n, '0');
int res = read<int>();
assert(res == 1);
}
J. Waiting for...
Monocarp 正在公交车站等车。不幸的是,有很多人也想乘坐公共汽车。
您会得到一份两类事件的清单:
- \(B \, b_i\) - 一辆有 \(b_i\) 个空座位的公交车到站;
- \(P \, p_i\) - \(p_i\) 人到达车站。
这些事件按时间顺序排列。
当一辆公共汽车到达时,会发生以下情况。公交车站的所有人(除了 Monocarp)都试图进入公交车。如果有足够的空位,他们就都上车。否则,会有一些人留在公交车站(进入公交车的人数等于空余座位数)。
如果所有的人(除了 Monocarp)都进入公交车后还有至少一个空座位,那么 Monocarp 也可以决定进入这辆公交车(但他可能会选择等另一辆公交车)。对于每辆公交车,您都必须确定 Monocarp 是否有可能乘坐该公交车。
输入
第一行包含一个整数 \(n\) - 事件数量。 \((1 \leq n \leq 10^3)\)
然后是 \(n\) 行。其中第 \(i\) 行包含第 \(i\) 个事件的描述,格式如下:
- \(B \, b_i\) \((1 \leq b_i \leq 10^6)\) - 一辆有 \(b_i\) 个空座位的公交车到站;
- \(P \, p_i\) \((1 \leq p_i \leq 10^6)\) - \(p_i\) 人到达车站。
输入的其他限制条件:至少有一个 \(B\) 类型的事件。
输出
对于 \(B\) 类型的每个事件,如果 Monocarp 有可能占用相应的公交车,则打印 "YES",否则打印 "NO"(不区分大小写)。
示例
输入
10
P 2
P 5
B 8
P 14
B 5
B 9
B 3
P 2
B 1
B 2
输出
YES
NO
NO
YES
NO
YES
解题思路
签到题,按题意进行模拟即可。
实现代码
void solve()
{
int n;
cin >> n;
ll sum = 0;
while (n--)
{
char c;
int x;
cin >> c >> x;
if (c == 'P')
sum += x;
else
{
sum -= x;
if (sum < 0)
{
YES;
sum = 0;
}
else
{
NO;
}
}
}
}
K. Grid Walk
您有一个 \(n \times n\) 网格和两个整数 \(a\) 和 \(b\)。行和列的编号都是从 1 到 \(n\)。我们把第 \(i\) 行和第 \(j\) 列的交点处的单元格记为 \((i,j)\)。
您现在站在 \((1,1)\) 单元格,想要移动到 \((n,n)\) 单元格。
假设您现在位于 \((i,j)\) 单元格;如果存在相应的单元格,您可以一步移动到 \((i,j+1)\) 单元格或 \((i+1,j)\) 单元格。
我们将 \((i,j)\) 单元格的成本定义为
(此处,\(\text{gcd}(x,y)\) 表示 \(x\) 和 \(y\) 的最大公约数)。从 \((1,1)\) 到 \((n,n)\) 的路径成本是所访问单元格(包括起始单元格和终点单元格)的成本之和。
找出成本最小的路线并打印其成本。
输入
唯一一行包含三个整数 \(n\)、\(a\) 和 \(b\) \((2 \leq n \leq 10^6; 1 \leq a,b \leq 10^6)\)。
输出
打印一个整数——从 \((1,1)\) 到 \((n,n)\) 的最便宜路线的成本。
示例
输入
4 2 4
输出
21
输入
10 210 420
输出
125
注意
第一个示例在上面的图片中描述。
解题思路
观察发现,无论我们如何操作,我们一定至少会加一遍所有的 \(\text{gcd}(i,a)\) 和 \(\text{gcd}(j,b)\) ,我们可操作的为剩下需要加上的值 \(v\)。
考虑极限情况: \(gcd(n,a)=1\) 且 \(gcd(n,b)=1\) ,则我们一定是走边角最优,除了必加值外,我们剩下加上的值都是 \(1\) 。
因此,对于任意 \(a,b,n\) 来说,我们一定是走到从第一行一直向右走,走到最远的 \(\text{maxi}=i\) 使得 \(gcd(a,i)=1\) ,然后再一直向下走,走到最远的 \(\text{maxj}=j\) 使得 \(gcd(b,j)=1\) 。然后再考虑剩下的位置这么走。
我们设 \(rn=n-\text{maxi}\) , \(rm=n-\text{maxj}\) ,可以发现 \(rn\) 和 \(rm\) 都比较小。
因为质数和任何数都互质,且质数在 \(10^6\) 内分布较为稠密,质数之间的最大间隔不会超过 \(200\),因此 \(rn \lt 200,rm \lt 200\)。可以直接进行 \(n^2\) 的 dp 。
状态转移方程:\(dp[i][j]=\min(dp[i-1][j],dp[i][j-1])+\gcd(i,a)+\gcd(j,b)\)
实现代码
void solve()
{
int n, a, b;
cin >> n >> a >> b;
int maxi = 1;
vi ga(n + 1);
for (int i = 1; i <= n; i++)
{
ga[i] = __gcd(i, a);
if (ga[i] == 1)
maxi = i;
}
int maxj = 1;
vi gb(n + 1);
for (int i = 1; i <= n; i++)
{
gb[i] = __gcd(i, b);
if (gb[i] == 1)
maxj = i;
}
int ans = maxi + maxj - 2;
for (int i = 1; i <= maxi; i++)
{
ans += ga[i];
}
for (int i = 1; i <= maxj; i++)
{
ans += gb[i];
}
int rn = n - maxi;
int rm = n - maxj;
vvi dp(rn + 1, vi(rm + 1, inf));
dp[0][0] = 0;
for (int i = 0; i <= rn; i++)
{
for (int j = 0; j <= rm; j++)
{
if (i > 0)
dp[i][j] = min(dp[i][j], dp[i - 1][j] + ga[maxi + i] + gb[maxj + j]);
if (j > 0)
dp[i][j] = min(dp[i][j], dp[i][j - 1] + ga[maxi + i] + gb[maxj + j]);
}
}
ans += dp[rn][rm];
cout << ans << "\n";
}
L. Bridge Renovation
最近,Monocarp 开始担任他家附近一个公园的园长。公园很大,甚至有一条小河把它分成几个区域。河上建有几座桥。其中有三座桥特别老旧,需要修理。
三座桥的长度相同,但宽度不同。它们的宽度分别为 18、21 和 25 个单位。
在公园翻新过程中,Monocarp 必须用新木板替换作为桥面的旧木板。
木板的标准长度为 60 个单位。Monocarp 已经知道每座桥需要 \(n\) 块木板。但由于桥的宽度不同,第一座桥需要长度为 18 的 \(n\) 块木板,第二座桥需要长度为 21 的 \(n\) 块木板,最后一座桥需要长度为 25 的 \(n\) 块木板。
负责翻修的工人可以将木板切割成若干部分,但拒绝将木板连接起来,因为这样会产生薄弱点,而且看起来很难看。
Monocarp 想买尽可能少的木板,但却苦于计算不出所需木板的数量。您能帮助他吗?
输入
第一行也是唯一一行包含一个整数 \(n\) \((1 \leq n \leq 1000)\)——三座桥所需的木板数量。
输出
打印一个整数——如果木板可以切割成若干部分,则 Monocarp 覆盖所有三座桥所需的最小标准长度木板数量(60 单位)。
示例
输入
1
输出
2
输入
3
输出
4
输入
1000
输出
1167
注意
在第一个示例中,可以将一块长度为 60 的木板切割成三块长度为 25、18 和 17 的木板,再将另一块长度为 60 的木板切割成两块长度为 39 和 21 的木板。这样,Monocarp 将会得到所有所需的木板。
解题思路
观察发现第一种和第二种的木板可以任意三三组合,剩下的和第三种只能任意两两组合,因此答案为 \(\lfloor \frac{2n}{3} \rfloor +\lceil \frac{2n\%3+n}{2} \rceil\)
实现代码
void solve()
{
int n;
cin >> n;
cout << (2 * n) / 3 + (2 * n % 3 + n + 1) / 2 << "\n";
}
N. Fixing the Expression
表达式是由三个字符组成的字符串,其中第一个和最后一个字符是数字(从 0 到 9),中间的字符是比较符号(<, = 或 >)。
如果比较符号与数字匹配,则表达式为真(例如,如果第一位数字严格小于最后一位数字,则比较符号应为 <)。
例如,表达式 1<3、4>2、0=0 为真,而 5>5、7<3 不是真。
给你一个字符串 \(s\),这是一个表达式。请尽可能少地更改字符,使 \(s\) 成为一个真表达式。请注意,如果 \(s\) 已经为真,则应保持原样。
输入
第一行包含一个整数 \(t\) \((1 \leq t \leq 300)\) - 测试用例数。
每个测试用例包含一行字符串 \(s\) \((|s| = 3\),\(s\) 的第一个和最后一个字符为数字,第二个字符为比较符号)。
输出
对于每个测试用例,打印一个由 3 个字符组成的字符串,即通过更改 \(s\) 中尽可能少的字符而得到的真表达式。如果有多个答案,则打印其中任何一个。
示例
输入
5
3<7
3>7
8=9
0=0
5<3
输出
3<7
8>7
8<9
0=0
0<3
解题思路
签到题,根据两边值的关系去修改符号即可。
实现代码
void solve()
{
string s;
cin >> s;
int a = s[0];
int b = s[2];
if (a < b)
s[1] = '<';
else if (a == b)
s[1] = '=';
else
s[1] = '>';
cout << s << "\n";
}
封面画师id:清风残影Sid