第三次题组 [Cloned] - Virtual Judge
A - Plus and Multiply
题目大意:
给定一个无限集合的生成规则,判断给定的数n是否在这个集合中。生成规则如下:
- 1属于这个集合。
- 如果x属于这个集合,那么x⋅a和x+b也属于这个集合。
解题思路:
对于每个测试用例,我们需要判断给定的数n是否符合集合的生成规则。我们可以通过迭代计算的方式逐步生成集合中的数,直到找到n或者超过n。
- 初始化一个布尔变量ok为0,用于表示是否找到n。
- 使用循环从1开始迭代计算集合中的数i,直到i超过n或者找到n为止。
-
- 在每次迭代中,判断是否存在一个数x,满足条件:(n - x) 可以被b整除。
- 若满足条件,则输出"YES",将ok置为1,并跳出循环。
- 若a的值为1,则跳出循环,因为无法继续生成新的数。
- 判断ok的值,若为0,则输出"NO"。
AC代码:
#include <iostream>
using namespace std;
int main() {
long long t;
cin >> t;
while (t--) {
long long n, a, b;
cin >> n >> a >> b;
int ok = 0;
for (long long i = 1; i <= n; i *= a) {
if ((n - i) % b == 0) {
cout << "YES" << endl;
ok = 1;
break;
}
//防止死循环
if (a == 1) {
break;
}
}
if (ok == 0) {
cout << "NO" << endl;
}
}
return 0;
}
第三次题组 [Cloned] - Virtual Judge
B - Air Conditioner
题目要求判断是否可以满足所有顾客的温度偏好范围。对于每个测试用例,首先读取测试用例的数量。然后,对于每个测试用例,读取顾客数量和初始温度。接下来,读取每个顾客的到达时间和温度偏好范围。最后,输出每个测试用例的结果。
为了解决这个问题,我们可以模拟时间的流逝和空调状态的改变。首先,我们初始化当前温度为初始温度,并设置一个变量 an 来跟踪上一个顾客的到达时间。然后,对于每个顾客,我们根据时间的流逝和空调状态的改变更新温度。我们根据顾客到达时间和上一个顾客到达时间之间的时间差来更新温度。然后,我们根据当前空调状态和顾客的温度偏好范围,更新最小温度和最大温度。如果最大温度小于最小温度,意味着无法满足顾客的温度偏好范围,将结果设置为 "NO"。最后,输出最终的结果。
AC代码:
#include<iostream>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int n, m;
cin >> n >> m;
int mint = m, maxt = m;
int an = 0;
string ans = "YES";
for (int i = 0; i < n; i++) {
int t1, l, r;
cin >> t1 >> l >> r;
mint -= (t1 - an);
maxt += (t1 - an);
an = t1;
maxt = min(r, maxt);
mint = max(l, mint);
if (maxt < mint)
ans = "NO";
}
cout << ans << endl;
}
return 0;
}
第三次题组 [Cloned] - Virtual Judge
D - Bargaining Table
题目大意:
Bob想在他的办公室放一张新的谈判桌。为了做到这一点,他仔细测量了办公室的房间,并画出了它的平面图:Bob的办公室是一个 n × m 米的矩形房间。房间的每个平方米要么被某些家具占据,要么为空闲的。一张谈判桌是矩形的,并且应该被放置在办公室的墙壁平行的位置上。Bob希望谈判桌能够容纳尽可能多的人,因此它的周长应该是最大的。帮助Bob找出他办公室中谈判桌的最大可能周长。
解题思路:
为了确定谈判桌的最大周长,我们需要考虑所有可能的谈判桌放置位置。我们可以使用动态规划来计算每个位置的可用空闲区域数目,并根据这些信息确定最大周长。
- 读取输入,包括办公室的尺寸和每个位置的状态(0表示空闲,1表示占用)。
- 创建一个二维数组d,用于记录每个位置的可用空闲区域数目。d[i][j] 表示以位置 (i, j) 为右下角的矩形区域内的空闲区域数目。这个值表示了从 (0, 0) 到 (i, j) 位置的矩形区域内,有多少个连续的空闲区域。
- 使用动态规划计算d数组:
-
- 对于每个位置(i, j),计算d[i][j]的值,表示以(i, j)为右下角的矩形区域内的空闲区域数目。
- 根据状态转移方程:d[i][j] = input[i][j] - calculateCellValue(i - 1, j - 1, d) + calculateCellValue(i, j - 1, d) + calculateCellValue(i - 1, j, d)。
- 其中,calculateCellValue函数用于处理边界情况,保证不会越界。
状态转移方程 d[i][j] = input[i][j] - calculateCellValue(i - 1, j - 1, d) + calculateCellValue(i, j - 1, d) + calculateCellValue(i - 1, j, d) 是用来计算 d[i][j] 的值的。
- input[i][j] 表示在 (i, j) 位置的状态,0 表示空闲,1 表示占用。
- calculateCellValue(i - 1, j - 1, d) 表示以 (i - 1, j - 1) 为右下角的矩形区域内的空闲区域数目。这个值用来消除计算 d[i][j] 时的重复计数。
- calculateCellValue(i, j - 1, d) 表示以 (i, j - 1) 为右下角的矩形区域内的空闲区域数目。这个值用来加上当前列 (i, j) 右侧的空闲区域数目。
- calculateCellValue(i - 1, j, d) 表示以 (i - 1, j) 为右下角的矩形区域内的空闲区域数目。这个值用来加上当前行 (i, j) 下方的空闲区域数目。
通过这些计算,我们可以得到 d[i][j] 的值,表示了以 (i, j) 为右下角的矩形区域内的空闲区域数目
通过计算 d 数组,我们可以得到整个办公室区域内每个位置的空闲区域数目,然后利用这些信息来确定最大周长的谈判桌放置位置。
- 使用循环遍历所有可能的谈判桌放置位置:
- 外层循环遍历所有可能的左上角位置(i, j)。
- 内层循环遍历所有可能的右下角位置(u, v),其中u >= i且v >= j。
- 根据d数组计算以(i, j)和(u, v)为对角线的矩形区域内的空闲区域数目x。
- 如果x等于0,表示该矩形区域全部为空闲区域,更新最大周长p为当前周长和(u + v - i - j)的较大值。
- 最终的最大周长为p + p + 4(两倍的周长加上四个角落)。
AC代码:
#include <iostream>
#include <vector>
using namespace std;
int getCellValue(int i, int j, const vector<vector<int>>& d) {
if (i < 0 || j < 0) {
return 0;
} else {
return d[i][j];
}
}
int calculateCellValue(int i, int j, const vector<vector<int>>& d) {
if (i < 0 || j < 0) {
return 0;
} else {
return d[i][j];
}
}
int main() {
int n, m;
cin >> n >> m;
vector<string> input(n);
for (int i = 0; i < n; i++) {
cin >> input[i];
}
vector<vector<int>> d(n, vector<int>(m, 0));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
d[i][j] = input[i][j] - '0' - calculateCellValue(i - 1, j - 1, d) + calculateCellValue(i, j - 1, d) + calculateCellValue(i - 1, j, d);
}
}
int p = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
for (int u = i; u < n; u++) {
for (int v = j; v < m; v++) {
int x = calculateCellValue(u, v, d) - calculateCellValue(u, j - 1, d)- calculateCellValue(i - 1, v, d) + calculateCellValue(i - 1, j - 1, d);
if (x == 0) {
p = max(p, u + v - i - j);
}
}
}
}
}
cout << p + p + 4 << endl;
return 0;
}
第三次题组 [Cloned] - Virtual Judge
E - Coins
题目要求根据最贵的硬币的面额n,找出最多数量的硬币方案,并按面额从高到低的顺序输出。每个硬币的面额必须能够被比它便宜的硬币面额整除。
首先,我们从最贵的硬币开始,逐渐减小面额。对于每个面额i,如果最贵的硬币的面额n能够整除i,那么i就是一个有效的硬币面额。我们将i赋值给n,并将其输出。由于要求输出面额从高到低,因此我们按顺序输出硬币面额即可。
AC代码:
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
for (int i = n; i > 0; i--) {
if (n % i == 0) {
n = i;
cout << n << " ";
}
}
return 0;
}
由于循环是从最大面额开始递减的,因此输出的硬币面额会按照降序排列。
第三次题组 [Cloned] - Virtual Judge
F - Alice, Bob and Chocolate
题目要求Alice和Bob进行吃巧克力的游戏。他们在一条直线上放置了n块巧克力。Alice从左到右吃巧克力,Bob从右到左吃巧克力。每块巧克力的吃完所需时间已知(Alice和Bob的吃速相同)。当一个玩家吃完一块巧克力后,立即开始吃下一块。不允许同时吃两块巧克力,也不允许中途停下来。如果Alice和Bob同时开始吃同一块巧克力,Bob会让给Alice。
我们需要计算Alice和Bob各自吃掉的巧克力数量。
思路是使用两个指针,一个从左到右,一个从右到左,分别表示Alice和Bob当前吃巧克力的位置。同时,维护两个变量aliceBars和bobBars来记录他们吃掉的巧克力数量。
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> bars(n);
for (int i = 0; i < n; i++) {
cin >> bars[i];
}
int aliceBars = 0;
int bobBars = 0;
int left = 0;
int right = n - 1;
int aliceTime = 0;
int bobTime = 0;
while (left <= right) {
if (aliceTime <= bobTime) {
aliceTime += bars[left];
aliceBars++;
left++;
} else {
bobTime += bars[right];
bobBars++;
right--;
}
}
cout << aliceBars << " " << bobBars << endl;
return 0;
}
第三次题组 [Cloned] - Virtual Judge
H - Sale
这个问题要求我们找到Bob能够通过购买电视机销售中获得的最大金额。Bob最多可以携带m台电视机,并希望最大化收益。
解题思路:
对数组进行升序排序,以获取价格按升序排列的顺序。
初始化一个变量"earnedMoney"为0,用于记录总共赚取的金额。
遍历排序后数组的前m个元素:
- 如果价格为负数,则表示Bob通过购买该电视机可以赚取金额。将价格的绝对值加到"earnedMoney"中。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
vector<int> prices(n);
for (int i = 0; i < n; i++) {
cin >> prices[i];
}
sort(prices.begin(), prices.end());
int earnedMoney = 0;
for (int i = 0; i < m; i++) {
if (prices[i] >= 0) {
break;
}
earnedMoney -= prices[i];
}
cout << earnedMoney << endl;
return 0;
}