Codeforces Round 952 (Div. 4)
A. Creating Words
AC code:
void solve() {
string a, b; cin >> a >> b;
swap(a[0], b[0]);
cout << a << ' ' << b << endl;
}
B. Maximum Multiple Sum
AC code:
void solve() {
int n; cin >> n;
int mx = 0, ans;
for (int i = 2; i <= n; i ++) {
int cnt = 0, ca = i;
while (ca <= n) {
cnt += ca;
ca += i;
}
if (cnt >= mx) mx = cnt, ans = i;
}
cout << ans << endl;
}
C. Good Prefixes
题意:定义一个好的数组中,存在一个元素等于其余所有元素的和,现在寻找大小为n的数组a中有多少前缀数组是好的;
思路:优先队列存取元素,迭代跑一遍即可;
AC code:
void solve() {
int n; cin >> n;
vector<int> a(n + 1);
for (int i = 1; i <= n; i ++) cin >> a[i];
int ans = 0;
if (a[1] == 0) ans += 1;
int mx = a[1], cnt = 0;
priority_queue<int> pq;
for (int i = 2; i <= n; i ++) {
if (a[i] > mx) {
pq.push(mx);
cnt += mx;
mx = a[i];
} else {
pq.push(a[i]);
cnt += a[i];
}
if (mx == cnt) ans ++;
}
cout << ans << endl;
}
D. Manhattan Circle
题意:在n*m的字符网格中,找到曼哈顿圆的圆心;
思路:分别找到字符为’#‘的坐标的最大最小值,横纵坐标相加除二即为圆心坐标;
AC code:
void solve() {
int n, m; cin >> n >> m;
char g[n + 1][m + 1];
int l = 2e9, r = -1, u = 2e9, d = -1;
for (int i = 1; i <= n; i ++) {
for (int j = 1; j <= m; j ++) {
char c; cin >> c;
if (c == '#') {
l = min(l, j), r = max(r, j);
u = min(u, i), d = max(d, i);
}
}
}
int x, y;
if (l == r) y = l;
else y = abs(r + l) / 2;
if (u == d) x = u;
else x = abs(d + u) / 2;
cout << x << ' ' << y << endl;
}
E. Secret Box
题意:有一个已知长宽高为x, y, z的盒子B在一个3D坐标系中,现在有一个体积为k的盒子s,通过自由定义一种s的长宽高,s在B中最多可能有多少种放置方法,s的角坐标一定为整数坐标;
思路:暴力枚举S可能的长宽高即可,假设长宽高为a, b, c, 那么该种可能的答案为(x - a) * (y - b) * (z - c);
AC code :
void solve() {
int x, y, z, k; cin >> x >> y >> z >> k;
int ans = 0;
for (int i = 1; i <= k / i; i ++) {
if (k % i) continue;
int ca = k / i;
for (int j = 1; j <= ca / j; j ++) {
if (ca % j) continue;
int t[4];
t[1] = i, t[2] = j, t[3] = ca / j;
for (int a = 1; a <= 3; a ++) for (int b = 1; b <= 3; b ++) for (int c = 1; c <= 3; c ++) {
if (a == b || a == c || b == c) continue;
if (t[a] > x || t[b] > y || t[c] > z) continue;
ans = max(ans, (x - t[a] + 1) * (y - t[b] + 1) * (z - t[c] + 1));
}
}
}
cout << ans << endl;
}
F. Final Boss
题意:打BOSS,BOSS的血量为h,我们有n种攻击方式,每回合可以使用任意次攻击,第 i i i种攻击的伤害为 a i a_i ai,但是会有 c i c_i ci的cd,即在x回合使用后,需要在x+ c i c_i ci回合才能再次使用该攻击;最少需要多少回合可以击败BOSS;
思路:二分回合数,每次计算当前回合数最多能造成的伤害;
注意,二分过程中会爆longlong!!!
AC code:
#include<bits/stdc++.h>
#define endl '\n'
#define int long long
#define fast() ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
using namespace std;
typedef long long LL;
typedef __int128 ll;
typedef pair<int, int> PII;
const int N = 2e5+10, M = 2001;
const int INF = 0x3f3f3f3f3f, MOD = 998244353;
int h, n;
int a[N], c[N];
bool check(int k) {
ll cnt = 0;
for (int i = 0; i < n; i ++) {
cnt += ll((max(0LL, k - c[i])) / c[i] + ((max(0LL, k - c[i])) % c[i] != 0) + 1) * a[i];
if (cnt >= (ll)h) return true;
}
if (cnt >= h) return true;
return false;
}
void solve() {
cin >> h >> n;
for (int i = 0; i < n; i ++) cin >> a[i];
for (int i = 0; i < n; i ++) cin >> c[i];
int l = 1, r = 1e14;
while (l < r) {
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
cout << l << endl;
}
signed main() {
fast();
int T = 1;
cin >> T;
while (T --) {
solve();
}
return 0;
}
G. D-Function
题意:假设D(n)为数字n的各个数位之和,在 1 0 l 10^l 10l < n < 1 0 r 10^r 10r中,有多少n满足 D(k*n) = k * D(n);
思路:打表可以发现,要想满足题目条件,k*n的各数位直接一定不能有进位,所以首先k一定小于10;
再就是就是有多少个数与k相乘后无进位,每位独立,直接快速幂计算即可;
AC code:
int qmi(int a, int k, int p) {
int res = 1;
while (k) {
if (k & 1) res = res * a % p;
a = a * a % p;
k >>= 1;
}
return res;
}
void solve() {
int l, r, k; cin >> l >> r >> k;
int ca = 9 / k + 1;
int ans = qmi(ca, r, MOD) % MOD - qmi(ca, l, MOD) % MOD;
cout << (ans + MOD) % MOD << endl;
}
H1. Maximize the Largest Component (Easy Version)
题意:
在n*m的网格中,可以任意将一行或一列变为’#‘,操作后整个图中最大的’#'联通块的大小为多少;
思路:
通过BFS以及一个染色数组来记录初始的每个联通块的大小,以及标记同一联通块;
然后暴力枚举当每行or每列染色时,连接当前行/列的最大联通块大小;
AC code:
int f[5] = {1, 0, -1, 0, 1};
void solve() {
cin >> n >> m;
vector<vector<char>> v(n + 1, vector<char>(m + 1));
vector<vector<int>> col(n + 1, vector<int>(m + 1, -1));
for (int i = 1; i <= n; i ++) for (int j = 1; j <= m; j ++) {
cin >> v[i][j];
}
int st = 1;
for (int i = 1; i <= n; i ++) for (int j = 1; j <= m; j ++) {
if (col[i][j] != -1 || v[i][j] == '.') continue;
queue<pair<int, int>> q;
q.push({i, j});
col[i][j] = st;
while (!q.empty()) {
auto [x, y] = q.front();
q.pop();
for (int t = 0; t < 4; t ++) {
int nx = x + f[t], ny = y + f[t + 1];
if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && col[nx][ny] == -1 && v[nx][ny] == '#') {
col[nx][ny] = st;
q.push({nx, ny});
}
}
}
st += 1;
}
map<int, int> sum;
for (int i = 1; i <= n; i ++) for (int j = 1; j <= m; j ++) {
sum[col[i][j]] ++;
}
int ans = 0;
map<int, int> us;
for (int i = 1; i <= n; i ++) {
int cnt = 0;
us.clear();
for (int j = 1; j <= m; j ++) {
if (v[i][j] == '.') cnt ++;
else {
if (!us[col[i][j]]) cnt += sum[col[i][j]], us[col[i][j]] += 1;
}
}
if (i > 1)
for (int j = 1; j <= m; j ++) {
if (!us[col[i - 1][j]] && v[i - 1][j] == '#') cnt += sum[col[i - 1][j]], us[col[i - 1][j]] += 1;
}
if (i < n)
for (int j = 1; j <= m; j ++) {
if (!us[col[i + 1][j]] && v[i + 1][j] == '#') cnt += sum[col[i + 1][j]], us[col[i + 1][j]] += 1;
}
ans = max(ans, cnt);
}
for (int j = 1; j <= m; j ++) {
int cnt = 0;
us.clear();
for (int i = 1; i <= n; i ++) {
if (v[i][j] == '.') cnt ++;
else {
if (!us[col[i][j]]) cnt += sum[col[i][j]], us[col[i][j]] += 1;
}
}
if (j > 1)
for (int i = 1; i <= n; i ++) {
if (!us[col[i][j - 1]] && v[i][j - 1] == '#') cnt += sum[col[i][j - 1]], us[col[i][j - 1]] += 1;
}
if (j < m)
for (int i = 1; i <= n; i ++) {
if (!us[col[i][j + 1]] && v[i][j + 1] == '#') cnt += sum[col[i][j + 1]], us[col[i][j + 1]] += 1;
}
ans = max(ans, cnt);
}
cout << ans << endl;
}