edu 183 div2 F + 2023 ICPC Hangzhou

edu 183 div2 F and 2023 ICPC Hangzhou

div2

F

所有的状态的数量很少,直接倍增搞一下就好了。

constexpr int N = 10, M = 2520, L = 50;
 
int a[N + 5], b[N + 5];
i64 st[L][N][M];
 
void solve() {
    int n = 0;
    i64 m = 0ll;
    std::cin >> n >> m;
    int lcm = 1;
    for (int i = 1; i <= n; ++i) {
        std::cin >> a[i];
        int g = std::__gcd(lcm, a[i]);
        lcm = lcm * a[i] / g;
    }
    for (int i = 1; i <= n; ++i) {
        std::cin >> b[i];
    }
 
    // 枚举轮数
    for (int i = 0; i < n; ++i) {
        // 枚举位置
        for (int j = 0; j < lcm; ++j) {
            if ((j + 1) % a[i + 1] == b[i + 1]) {
                st[0][i][j] = 0;
            }
            else {
                st[0][i][j] = 1;
            }
        }
    }
 
    for (int l = 1; l < L; ++l) {
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < lcm; ++j) {
                i64 dis = st[l - 1][i][j];
                st[l][i][j] = dis + st[l - 1][(i + (1ll << l - 1)) % n][(j + dis) % lcm];
            }
        }
    }
 
    i64 ans = -1;
    if (st[L - 1][0][0] >= m) {
        i64 round = 0ll;
        i64 pos = 0;
        for (int i = L - 1; i >= 0; --i) {
            i64 dis = st[i][round % n][pos % lcm];
            if (pos + dis >= m) {
                continue;
            }
 
            pos += dis;
            round |= (1ll << i);
        }
        ans = round + 1ll;
    }
    std::cout << ans << '\n';
}

ICPC Hangzhou

D

竟然还可以这样解方程。

首先第二个式子中的每项都不能太大,就设除了首尾两项的和都为 1,最简单的赋值是从第二个数开始依次赋值 2 和 -1,对于前后两个数,令 y 为 1 解方程就好。

G

由于最短路肯定不走回头路,所以我们可以认为,除了一开始有蛇身的格子,在其他的格子都不会遇到蛇身。对于有蛇身的格子,假设格子上是倒数第 \(i\) 个身体,则至少要移动 \(i\) 步(不论是移动还是缩短身体),所以我们可以直接跑最短路,在蛇身处注意取max就好了。然后就是不用特意考虑取模,直接用 u64 存答案就好了。

int dx[4] = { 0, 0, 1, -1 };
int dy[4] = { 1, -1, 0, 0 };

void solve() {
    int n = 0, m = 0, k = 0;
    std::cin >> n >> m >> k;
    std::vector pos(k, std::array<int, 2>{});
    for (auto &[x, y] : pos) {
        std::cin >> x >> y;
        x -= 1;
        y -= 1;
    }
    std::vector g(n, std::vector(m, 0ull));
    for (auto &v : g) {
        std::string s;
        std::cin >> s;
        for (int i = 0; i < m; ++i) {
            v[i] = (s[i] == '.' ? 0ull : Inf);
        }
    }

    for (int i = 1; i < k; ++i) {
        const auto &[x, y] = pos[i];
        g[x][y] = k - i;
    }

    auto toH = [&](const int x, const int y) -> int {
        return x * m + y;
    };
    auto toP = [&](const int val) -> std::array<int, 2> {
        return { val / m, val % m };
    };
    std::priority_queue<std::pair<u64, int>, std::vector<std::pair<u64, int>>, std::greater<std::pair<u64, int>>> pq;
    std::vector<u64> dis(n * m, Inf);
    std::vector vis(n * m, false);

    dis[toH(pos[0][0], pos[0][1])] = 0ull;
    pq.push(std::make_pair(0, toH(pos[0][0], pos[0][1])));
    while (not pq.empty()) {
        const auto [d, cur] = pq.top();
        pq.pop();

        if (vis[cur]) {
            continue;
        }

        vis[cur] = true;

        const auto [x, y] = toP(cur);
        for (int i = 0; i < 4; ++i) {
            int tx = x + dx[i];
            int ty = y + dy[i];
            if (tx < 0 || ty < 0 || tx >= n || ty >= m) {
                continue;
            }
            int to = toH(tx, ty);
            if (g[tx][ty] == Inf || vis[to]) {
                continue;
            }

            if (dis[to] > std::max(g[tx][ty], d + 1ull)) {
                dis[to] = std::max(g[tx][ty], d + 1ull);
                pq.push(std::make_pair(dis[to], to));
            }
        }
    }

    u64 ans = 0ll;
    for (int i = 0; i < n * m; ++i) {
        if (dis[i] != Inf) {
            ans += dis[i] * dis[i];
        }
    }
    std::cout << ans << '\n';
}
posted @ 2025-10-11 00:31  Young_Cloud  阅读(3)  评论(0)    收藏  举报