ABC 368

D - Minimum Steiner Tree

https://atcoder.jp/contests/abc368/tasks/abc368_d

$V_1$ から DFS して、子または自身が $V_i$ に含まれていればそのノードを残す。

vvint graph;
vint visited;
set<int> memo;
int ans = 0;

bool dfs(int now) {
    bool res = false;
    if (memo.count(now))
        res = true;

    for (int nx : graph[now]) {
        if (visited[nx])
            continue;
        visited[nx] = 1;

        bool x = dfs(nx);
        res = res || x;

        // short-circuit で以下のよう書くと dfs が実行されない
        // res = res || dfs(nx)
    }

    if (res)
        ans++;
    return res;
}

void solve() {
    int n, k;
    cin >> n >> k;
    graph = vvint(n);
    rep(i, n - 1) {
        int u, v;
        cin >> u >> v;
        u--, v--;
        graph[u].push_back(v);
        graph[v].push_back(u);
    }

    vint nodes(k);
    rep(i, k) {
        cin >> nodes[i];
        nodes[i]--;
    }

    for (int x : nodes)
        memo.insert(x);

    visited = vint(n, 0);
    visited[nodes[0]] = 1;

    dfs(nodes[0]);
    cout << ans << endl;
}

F - Dividing Game

解説 AC

void solve() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    ll N;
    cin >> N;
    vll A(N);
    rep(i, N) cin >> A[i];

    int mx = 1e5 + 5;
    vll sieve(mx, 0);
    rep2(i, 2, mx) {
        for (int j = i; j < mx; j += i) {
            if (sieve[j] == 0)
                sieve[j] = i;
        }
    }

    auto factor_sum = [&](int x) -> int {
        int ans = 0;
        while (x != 1) {
            int d = sieve[x];
            while (x % d == 0) {
                ans++;
                x /= d;
            }
        }
        return ans;
    };

    vll nim;
    rep(i, N) {
        nim.push_back(factor_sum(A[i]));
    }

    ll sum = 0;
    for (ll x : nim)
        sum ^= x;
    string ans = "Anna";
    if (sum == 0) {
        ans = "Bruno";
    }
    cout << ans << endl;
}