AtCoder Beginner Contest 198
The competition link is here
Question A and B is too easy, so i won't write the editorial.
C - Compass Walking
Problem Statement
You are standing at the origin of a two-dimensional plane. For each step you can move to a point whose your distance from you current position is exactly (R) (the coordinate of the destination of a move do not have to be intergers), find the minimum number of steps you has to take before reaching ((X, Y)).
Constraints
-
(1 le R le 10^5)
-
(0 le X, Y le 10^5)
-
((X,Y) eq (0, 0))
-
All values in input are integers
Solution
好吧,还是写中文博客比较快。这题就是要考虑一个特殊情况。
分两种情况考虑,显然是走两点之间的直线上,不妨设距离为(dist):
-
恰好走完:(dist \% R == 0), 则直接除即可,(ans = dist/R)
-
不能恰好走完:
- (dist > R), 向上取整即可,考虑最后一步无法恰好达到则需要转为两步,(ans=lceil dist/R ceil)
- (dist < R), 特判为(2),至少需要两次。
Code
using ll = long long;
void solve(){
ll r, x, y;
std::cin >> r >> x >> y;
ll ans = ceil(sqrt(x * x + y * y) / r);
if (x * x + y * y < r * r) ans = 2;
std::cout << ans << "
";
}
D - Send More Money
Problem Statement
给定三个字符串(S_1, S_2, S_3),要求(S_1 + S_2 = S_3)。要求给出(N_1, N_2, N_3), 满足:
- (N_1 + N_2 = N_3)
- 每个字母代表且仅代表一个数字,同理数字也只代表最多一个。
- 不能有前导零
Constraints
-
Each of (S_1, S_2, S_3) is a string of length between (1) and (10) (inclusive) consisting of lowercase English letters.
Solution
比赛的时候没写出来,显然多于(10)个字母就直接没有解。少于(10)个的直接用next_permutation
暴力找,再特判前导零即可。
Code
void bad(){
std::cout << "UNSOLVABLE
";
exit(0); // 直接退出
}
void solve(){
vt<string> s(3);
rep (i, 0, 3) std::cin >> s[i];
map<char, int> mp;
for (auto v: s){
for (auto c: v) ++ mp[c];
}
if (mp.size() > 10) bad();
int m = mp.size();
string tar = "";
vt<int> num(10);
iota(all(num), 0);
for (auto e: mp) tar += e.first;
auto get_val = [&](char ch){
rep (i, 0, m){
if (ch == tar[i]) return num[i];
}
return -1ll;
};
do {
if (get_val(s[0].front()) == 0 or get_val(s[1].front()) == 0 or get_val(s[2].front()) == 0) continue;
int x1(0), x2(0), x3(0);
for (auto ch: s[0]){
x1 *= 10;
x1 += get_val(ch);
}
for (auto ch: s[1]){
x2 *= 10;
x2 += get_val(ch);
}
for (auto ch: s[2]){
x3 *= 10;
x3 += get_val(ch);
}
if (x1 + x2 == x3){
std::cout << x1 << "
";
std::cout << x2 << "
";
std::cout << x3 << "
";
return;
}
} while (next_permutation(all(num)));
std::cout << "UNSOLVABLE
";
}
E - Unique Color
Problem Statement
每个点有自己的颜色,给一颗树,并定义好的点为:
- 从点1到该点的最短路径中不存在重复颜色则为好的点。
请找到所有好的点。
Constraints
- (2≤N≤10^5)
- (1≤Ci≤10^5)
- (1≤Ai,Bi≤N)
- The given graph is a tree.
- All values in input are integers.
Solution
这题WA
了几发,没看清楚题目。
由于这个是树结构,则一次从结点(1)的dfs
就可以找到最短路径。(假如是带权图等,我们可以用基于heap
的dijkstra
并记录路径便可以保证时间复杂度。)需要注意的是,我们并不能简单的记录路径上某个颜色是否用过。我们应该记录颜色的数量,否则我们可能会误判,因为dfs
访问之后需要进行回溯,所以假如用0-1变量的话直接清空会导致误判没有改颜色,实际上我们应该用++
和–
进行处理。
Code
const int maxn = 1e5 + 50;
vt<int> E[maxn];
int color[maxn], use[maxn];
void solve(){
mst(use, 0);
int n; std::cin >> n;
rep (i, 1, n + 1) std::cin >> color[i];
rep (i, 0, n + 1) E[i].clear();
rep (i, 0, n - 1){
int u, v; std::cin >> u >> v;
E[u].pb(v), E[v].pb(u);
}
vt<int> ans;
function<void(int, int)> dfs = [&](int cur, int fa){
if (!use[color[cur]]) ans.pb(cur);
++use[color[cur]]; // 增加访问
for (auto go: E[cur]){
if (go == fa) continue;
dfs(go, cur);
--use[color[go]]; // 访问结束
}
};
dfs(1, 0);
sort(all(ans));
for (auto x: ans) std::cout << x << "
";
}