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';
}