A. Long Comparison
题目概述: 比较 x 1 × 1 0 p 1 x1 \times10^{p1} x1×10p1 和 x 2 × 1 0 p 2 x2 \times10^{p2} x2×10p2 的大小。
思路:
观察数据范围,
x
x
x 最大不超过
1
0
6
10^6
106 ,所以当
p
1
−
p
2
>
6
p1 - p2 > 6
p1−p2>6 的时候,就可以判定 第一个数大于第二个,相反同理。
如果第一个条件不能判断出,我们让
p
1
,
p
2
p1, p2
p1,p2 中较大值(称为
p
m
p_m
pm)减去较小值,较小值为
0
0
0, 此时
p
m
p_m
pm 的值不会超过
1
0
6
10^6
106 可以直接乘到相应的
x
x
x 上比较大小。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
char solve() {
ll x1, p1, x2, p2;
cin >> x1 >> p1;
cin >> x2 >> p2;
ll t = min(p1, p2);
p1 -= t;
p2 -= t;
if(p1 > 6) return '>';
else if(p2 > 6) return '<';
while(p1 --) x1 *= 10;
while(p2 --) x2 *= 10;
if(x1 > x2) return '>';
else if(x1 < x2) return '<';
else return '=';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
freopen("D:/Cpp/program/Test.in", "r", stdin);
freopen("D:/Cpp/program/Test.out", "w", stdout);
#endif
int t;
cin >> t;
while(t --)
cout << solve() << '\n';
}
B. Absent Remainder
题目概述:
一个长度为
n
n
n 的数组
a
a
a, 现在要求在数组中找到 ⌊
n
2
n\over2
2n⌋ 对
(
x
,
y
)
(x, y)
(x,y), 满足
x
x
x
m
o
d
mod
mod
y
y
y 没有在数组
a
a
a 中出现过。
思路:
两个数相模得到的数一定会小于这两个数,所以直接选数组中任意 ⌊
n
2
n\over2
2n⌋ 对非最小数与 数组中最小的数即可。
代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
typedef pair<int, int> PII;
const int N = 2e5 + 10;
int n, a[N];
void solve() {
cin >> n;
for(int i = 1; i <= n; i ++) cin >> a[i];
sort(a + 1, a + n + 1);
int temp = n / 2;
for(int i = temp; i != 0; i --) {
cout << a[i + 1] << ' ' << a[1] << '\n';
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
freopen("D:/Cpp/program/Test.in", "r", stdin);
freopen("D:/Cpp/program/Test.out", "w", stdout);
#endif
int t;
cin >>t;
while(t --) {
solve();
}
}
C. Poisoned Dagger
题目概述:
一个人攻击一次龙,龙会中毒
k
k
k 秒,每次攻击会刷新中毒时间,现在给出每次进行攻击的时间和龙的总血量
h
h
h, 求保证能杀死龙的情况下最小的
k
k
k。
思路:
对龙在一段时间内造成的伤害为
k
k
k 和两次攻击时间直接的间隔的最小值,用这个性质去二分答案即可。
代码:
cpp
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
typedef pair<int, int> PII;
const int N = 110;
ll n, h;
ll a[N];
bool check(ll m) {
ll res = 0;
for(int i = 1; i < n; i ++) {
res += min(a[i + 1] - a[i], m);
if(res >= h) break;
}
res += m;
return res >= h;
}
void solve() {
cin >> n >> h;
for(int i = 1; i <= n; i ++) cin >> a[i];
ll l = 0, r = h;
while(l < r) {
ll mid = l + r >> 1;
if(check(mid)) r = mid;
else l = mid + 1;
}
cout << l << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
freopen("D:/Cpp/program/Test.in", "r", stdin);
freopen("D:/Cpp/program/Test.out", "w", stdout);
#endif
int t;
cin >> t;
while(t --)
solve();
return 0;
}
E. Crazy Robot
题目概述:
L
L
L 是需要到达的地方 ‘
.
.
.’ 是 可走的, ‘#’ 是不可走的,现在给机器人下达命令,机器人会按照不是命令所指的方向前进,问哪些点在我们下达命令后机器人可以被 ‘赶’ 到
L
L
L。
思路:
要使得下达命令后机器人会到达实验室,这个格子到
L
L
L 的路径上的每一个格子都应当满足:
- 有一个方向是可以前往 L L L 的
- 除了上面的方向至多再可以有一个方向可以走。
所以我们考虑从 L L L 出发,寻找一条满足出度 ≤ 1 \le 1 ≤1 的路径。
先预处理出所有点的出度,然后从
L
L
L 开始遍历,找到一个点就使得度减小
1
1
1 , 度小于等于
1
1
1 时就说明该点满足并从该点继续开始更新。简单的来说就是跑一个拓扑排序。
本题数据不足以开二位数组,所以需要一维二维相互转换:
n
o
d
e
=
x
∗
(
m
)
+
y
node = x * (m) + y
node=x∗(m)+y (
m
m
m 为网格列数)
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e6 + 10;
const pair<int, int> moves[] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};
int n, m;
void solve() {
cin >> n >> m;
vector<string> s(n);
PII start;
for(int i = 0; i < n; i ++) cin >> s[i];
//预处理出所有点的度
vector<int> dir(n * m);
for(int i = 0; i < n; i ++)
for(int j = 0; j < m; j ++)
if(s[i][j] == '.') {
for(auto [dx, dy] : moves) {
int x = i + dx, y = j + dy;
if(x < 0 || x >= n || y < 0 || y >= m || s[x][y] == '#') continue;
dir[i * m + j] ++;
}
} else if(s[i][j] == 'L') start = {i, j};
queue<PII> q;
q.emplace(start.first, start.second);
int star = start.first * m + start.second;
dir[star] = -1;
while(q.size()) {
auto t = q.front();
q.pop();
int x = t.first, y = t.second;
if(x * m + y != star) {
s[x][y] = '+';
}
for(auto [dx, dy] : moves) {
int a = x + dx, b = y + dy;
if(a < 0 || a >= n || b < 0 || b >= m) continue;
if(s[a][b] == '#' || dir[a * m + b] == -1) continue;
dir[a * m + b] --;
if(dir[a * m + b] <= 1) { //能去的其他方向数量小于等于 1 时候就说明该点满足
dir[a * m + b] = -1;
q.emplace(a, b);
}
}
}
for(int i = 0; i < n; i ++) cout << s[i] << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
freopen("D:/Cpp/program/Test.in", "r", stdin);
freopen("D:/Cpp/program/Test.out", "w", stdout);
#endif
int t;
cin >> t;
while(t --) {
solve();
}
}