AtCoder Beginner Contest 198[C-E]

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就可以找到最短路径。(假如是带权图等,我们可以用基于heapdijkstra并记录路径便可以保证时间复杂度。)需要注意的是,我们并不能简单的记录路径上某个颜色是否用过。我们应该记录颜色的数量,否则我们可能会误判,因为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 << "
";
}
原文地址:https://www.cnblogs.com/Last--Whisper/p/14649806.html