A. Creating Words
时间限制:1秒 空间限制:256MB 输入:标准输入 输出:标准输出
问题描述
Matthew 得到了两个长度为 3 的字符串 a 和 b。他觉得把 a 的第一个字符与 b 的第一个字符交换来创建两个新词特别有趣。他希望你输出交换后的 a 和 b。
注意,新的单词不一定不同。
输入格式
第一行包含一个整数 t (),表示测试用例的数量。
每个测试用例的第一行也是唯一的一行包含两个用空格分隔的字符串 a 和 b,它们的长度均为 3。这些字符串只包含小写的拉丁字母。
输出格式
对于每个测试用例,输出交换后的字符串 a 和 b,用空格分隔。
样例输入
样例输出
思路
按照题目要求交换两个字符串的第一个字母。
代码
#include <bits/stdc++.h>
using namespace std;
int t;
inline int read() {
int x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int main() {
t = read();
while (t--) {
string a, b;
cin >> a >> b;
putchar(b[0]);
for (int i = 1; i < a.length(); i++) putchar(a[i]);
putchar(' '), putchar(a[0]);
for (int i = 1; i < b.length(); i++) putchar(b[i]);
putchar('\n');
}
return 0;
}
B. Maximum Multiple Sum
时间限制:1秒 空间限制:256MB 输入:标准输入 输出:标准输出
问题描述
给定一个整数 n,找到一个整数 x,使得满足以下条件:
- 在满足条件的所有 x 中,使得不超过 n 的 x 的倍数的和最大。形式化地,x + 2x + 3x + ⋯ + kx(其中 kx ≤ n)的和在所有可能的 x 中是最大的。
输入格式
第一行包含一个整数 t (),表示测试用例的数量。
每个测试用例包含一个整数 n ()。
输出格式
对于每个测试用例,输出一个整数,即最优的 x 值。可以证明,只有一个唯一的答案。
样例输入
样例输出
注释
对于 n=3,可能的 x 值是 2 和 3。小于或等于 n 的所有 2 的倍数的和是 2,而小于或等于 n 的所有 3 的倍数的和是 3。因此,3 是 x 的最优值。
对于 n = 15,x 的最优值是 2。小于或等于 n 的所有 2 的倍数的和是 2 + 4 + 6 + 8 + 10 + 12 + 14 = 56,可以证明这是所有其他可能的 x 值中最大的和。
思路
从 2 到 n 暴力枚举每一个 x,找出最优的 x 值。
代码
#include <bits/stdc++.h>
using namespace std;
int t, n;
inline int read() {
int x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int main() {
t = read();
while (t--) {
n = read();
int ans = 2, tar = 0;
for (int i = 2; i <= n; i++) {
int sum = 0;
for (int j = 1; j * i <= n; j++) sum += j * i;
if (sum >= tar) ans = i, tar = sum;
}
printf("%d\n", ans);
}
return 0;
}
C. Good Prefixes
时间限制:2秒 空间限制:256MB 输入:标准输入 输出:标准输出
问题描述
Alex 认为某个数组是好的,如果存在某个元素可以表示为所有其他元素的和(如果没有其他元素,则所有其他元素的和为0)。例如,数组 [1,6,3,2] 是好的,因为 1 + 3 + 2 = 6。此外,数组 [0] 也是好的。然而,数组 [1,2,3,4] 和 [1] 不是好的。
Alex 有一个数组 。帮他计算数组 a 的非空前缀中好的数量。换句话说,计算有多少个整数 i (),使得长度为 i 的前缀 (即 ) 是好的。
输入格式
输入的第一行包含一个整数 t (),表示测试用例的数量。
每个测试用例的第一行包含一个整数 n (),表示数组中的元素数量。
每个测试用例的第二行包含 n 个整数 (),表示数组中的元素。
保证所有测试用例中 n 的总和不超过 。
输出格式
对于每个测试用例,输出一个整数,表示数组 a 的好的非空前缀的数量。
样例输入
样例输出
注释
在第四个测试用例中,数组有五个前缀:
- 前缀 [0] 是一个好的数组,正如题目中所述;
- 前缀 [0,1] 不是一个好的数组,因为 0 ≠ 1;
- 前缀 [0,1,2] 不是一个好的数组,因为 0 ≠ 1 + 2,1 ≠ 0 + 2,2 ≠ 0 + 1;
- 前缀 [0,1,2,1] 是一个好的数组,因为 2 = 0 + 1 + 1;
- 前缀 [0,1,2,1,4] 是一个好的数组,因为 4 = 0 + 1 + 2 + 1。
正如你所看到的,其中有三个是好的,所以答案是 3。
思路
如果一段前缀是一个好数组,那么这个数组种最大的数一定等于其他数的和。我们只需要维护前缀和,再用单调队列(单调递减队列)维护每段前缀里面最大的数的下标,最后判断最大的数是否等于其他数的和。
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 10;
int t, n, a[N], sum[N];
inline int read() {
int x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
deque<int> q;
signed main() {
t = read();
while (t--) {
n = read();
for (int i = 1; i <= n; i++) a[i] = read(), sum[i] = sum[i - 1] + a[i];
int cnt = 0;
for (int i = 1; i <= n; i++) {
while (q.size() && a[i] > a[q.back()]) q.pop_back();
q.push_back(i);
if (2 * a[q.front()] == sum[i]) cnt++;
// 判断条件等价于 a[q.front()] == sum[i] - a[q.front()]
} q.clear();
printf("%lld\n", cnt);
}
return 0;
}
D. Manhattan Circle
时间限制:2秒 空间限制:256MB 输入:标准输入 输出:标准输出
问题描述
给定一个由 '.' 和 '#' 字符组成的 n 行 m 列的网格,在该网格上存在一个完整的曼哈顿圆。网格的左上角坐标为 (1,1),右下角坐标为 (n,m)。
如果点 (a,b) 属于以 (h,k) 为中心的曼哈顿圆,则 |h−a|+|k−b|<r,其中 r 是一个常数。
在网格上,属于曼哈顿圆的点被标记为 '#'. 找出圆心的坐标。
输入格式
第一行包含一个整数 t (),表示测试用例的数量。
每个测试用例的第一行包含两个整数 n 和 m (),分别表示网格的高度和宽度。
接下来的 n 行每行包含 m 个字符 '.' 或 '#'。如果字符是 '#',那么该点是曼哈顿圆的一部分。
保证所有测试用例中 n⋅m 的总和不超过 ,并且网格上存在一个完整的曼哈顿圆。
输出格式.
对于每个测试用例,输出两个整数,表示圆心的坐标。
样例输入
样例输出
思路
找出所有 '#' 方格的最大最小横纵坐标,取最大最小值的平均值
代码
#include <bits/stdc++.h>
using namespace std;
int t, n, m;
inline int read() {
int x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int main() {
t = read();
while (t--) {
n = read(), m = read();
char s[n + 5][m + 5];
for (int i = 0; i < n; i++) scanf("%s", s[i]);
int minx = n - 1, maxx = 0, miny = m - 1, maxy = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (s[i][j] == '#') {
minx = min(minx, i), maxx = max(maxx, i);
miny = min(miny, j), maxy = max(maxy, j);
}
}
}
int x = (minx + maxx) / 2 + 1, y = (miny + maxy) / 2 + 1;
printf("%d %d\n", x, y);
}
return 0;
}
E. Secret Box
时间限制:2秒 空间限制:256MB 输入:标准输入 输出:标准输出
问题描述
Ntarsis 有一个边长分别为 x、y 和 z 的盒子 B。这个盒子位于三维坐标平面内,从 (0,0,0) 延伸到 (x,y,z)。
Ntarsis 有一个秘密盒子 S。他想选择 S 的尺寸,使得所有边长都是正整数,且 S 的体积为 k。他可以将 S 放置在 B 内的某个位置,使得:
- S 与所有坐标轴平行。
- S 的每个角都在整数坐标上。
- S 是魔法盒子,所以当放置在 B 内的整数位置时,它不会掉到地上。
在所有可能的选择 S 尺寸的方法中,确定 Ntarsis 可以选择将他的秘密盒子 S 放置在 B 内的不同位置的最大数量。Ntarsis 一旦选择了 S 的边长,就不会旋转 S。
输入格式
第一行包含一个整数 t,表示测试用例的数量 ()。接下来是每个测试用例的描述。
每个测试用例的第一行包含四个整数 x、y、z 和 k ()。
保证所有测试用例中 x 的总和,y 的总和,z 的总和均不超过 2000。
注意,k 可能无法适应标准的 32 位整数数据类型。
输出格式
对于每个测试用例,将答案作为一个整数输出在新的一行上。如果没有办法选择 S 的尺寸使其适合 B,则输出 0。
样例输入
样例输出
思路
枚举 S 方格与 x,y 轴平行的边的长度,算出与 z 轴平行的边的长度,统计答案(具体看代码)。
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
int t, x, y, z, k;
inline int read() {
int x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
signed main() {
t = read();
while (t--) {
x = read(), y = read(), z = read(), k = read();
int ans = 0, num = 0;
for (int i = 1; i <= x; i++) {
if (k % i != 0 || y * z < k / i) continue;
// S的每个顶点都是整数,所以边长一定是一定是整数
for (int j = 1; j <= y; j++) {
if ((k / i) % j != 0 || k / (i * j) > z) continue;
// S的每个顶点都是整数,所以边长一定是一定是整数
num = (x - i + 1) * (y - j + 1) * (z - (k / (i * j)) + 1);
// 分别统计在x,y,z方向上有多少种放置的可能性,答案即为三者乘积
ans = max(ans, num);
}
}
printf("%lld\n", ans);
}
return 0;
}
F. Final Boss
时间限制:2秒 空间限制:256MB 输入:标准输入 输出:标准输出
问题描述
你正在你最喜欢的视频游戏中面对最终boss。敌方boss有 h 点生命值。你的角色有 n 种攻击方式。第 i 种攻击对boss造成 点伤害,但有 回合的冷却时间,意味着如果你在第 x 回合使用了这种攻击,那么下一次你可以使用这种攻击的回合是 。每个回合,你可以同时使用所有当前不在冷却时间内的攻击。如果所有攻击都在冷却时间内,你什么也做不了,跳到下一回合。
最初,所有攻击都没有冷却时间。你需要多少回合才能击败boss?当boss的生命值为0或更少时,boss就被击败了。
输入格式
第一行包含一个整数 t (),表示测试用例的数量。
每个测试用例的第一行包含两个整数 h 和 n (),分别表示 boss 的生命值和你的攻击数量。
每个测试用例的第二行包含 n 个整数 (),表示每种攻击的伤害值。
每个测试用例的第三行包含 n 个整数 (),表示每种攻击的冷却时间。
保证所有测试用例中 h 和 n 的总和不超过 。
输出格式
对于每个测试用例,输出一个整数,即击败boss所需的最小回合数。
样例输入
样例输出
注释
对于第一个测试用例,你可以在第一回合使用攻击1和攻击2,总共造成3点伤害,击败boss。
对于第二个测试用例,你可以在3个回合内击败boss,具体如下:
回合1:使用攻击1和攻击2,对boss造成3点伤害。boss现在剩下2点生命值。
回合2:使用攻击2,对boss造成1点伤害。boss现在剩下1点生命值。
回合3:使用攻击1,对boss造成2点伤害。boss现在剩下-1点生命值。由于其生命值小于或等于0,你击败了boss。
对于第六个测试用例:记得使用64位整数,因为答案可能会很大。
思路
将所有攻击放入一个优先队列种,用优先队列当前时间来从小到大排序。每次取队头元素进行操作,如果击败了boss,输出当前时间,否则将对头元素的时间加上对应的冷却时间再次放入优先队列中。
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 10;
int t, h, n, a[N], c[N];
struct node {
int d, t, id;
bool operator<(const node& x) const{
return x.t < t;
}
};
inline int read() {
int x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
signed main() {
t = read();
while (t--) {
h = read(), n = read();
for (int i = 1; i <= n; i++) a[i] = read();
for (int i = 1; i <= n; i++) c[i] = read();
priority_queue<node> q;
for (int i = 1; i <= n; i++) q.push({a[i], 1, i});
while (!q.empty()) {
node cur = q.top(); q.pop();
h -= cur.d;
if (h <= 0) { printf("%lld\n", cur.t); break; }
q.push({cur.d, cur.t + c[cur.id], cur.id});
}
}
return 0;
}
G. D-Function
问题描述
设 D(n) 表示 n 的各位数字之和。有多少个整数 n 满足 的条件,使得 ?输出答案对 取模的结果。
输入格式
第一行包含一个整数 t (),表示测试用例的数量。
每个测试用例包含三个整数 l, r 和 k()。
输出格式
对于每个测试用例,输出一个整数,即答案对 取模的结果。
样例输入
样例输出
注释
注意
对于第一个测试用例,唯一满足条件的 n 值是 1 和 2。
对于第二个测试用例,唯一满足条件的 n 值是 1, 10 和 11。
对于第三个测试用例,所有 10(包括)到 100(不包括)之间的 n 值都满足条件。
思路
我们发现,如果要满足题目条件,那么 kn 一定不能出现进位的情况,也就是说 k 一定要小于 10。
对于一个长度为 i + 1 的数来说,若 ,第一位有 q - 1 种选择,其他位有 q 种选择,总共有 ,因此在 范围内,总共有 个 n符合题目要求。
接下来只需要用一个快速幂求出结果即可
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 1e9 + 7;
int t, l, r, k;
inline int read() {
int x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int qpow(int a, int n) {
int res = 1LL;
while (n) {
if (n & 1) res = res * a % mod;
a = a * a % mod;
n >>= 1;
}
return res;
}
signed main() {
t = read();;
while (t--) {
l = read(), r = read(), k = read();
if (k >= 10) { putchar('0'), putchar('\n'); continue; }
int num = 9 / k + 1;
printf("%lld\n", qpow(num, l) * (qpow(num, r - l) - 1) % mod);
}
return 0;
}