AtCoder Beginner Contest 400
A - ABC400 Party
点击查看代码
void solve() {
int n;
std::cin >> n;
if (400 % n) {
std::cout << -1 << "\n";
} else {
std::cout << 400 / n << "\n";
}
}
B - Sum of Geometric Series
模拟,大于1e9就中断。
点击查看代码
void solve() {
i64 n, m;
std::cin >> n >> m;
i64 ans = 0;
for (i64 i = 1, j = 0; j <= m && ans <= 1e9; ++ j, i *= n) {
ans += i;
}
if (ans <= 1e9) {
std::cout << ans << "\n";
} else {
std::cout << "inf\n";
}
}
C - 2^a b^2
题意:判断\([1, n]\)里有多少数可以表示为\(2^a \times b^2\)。
我们可以枚举\(a\)的幂,然后二分\(b\)的范围。但当\(a > 2\)时,发现\(2^a \times b^2\)可以表示为\(2^{a-2} \times (2b)^{2}\)。这意味着这个数之前被计算过了。所以我们只需要枚举\(2^1\)和\(2^2\)。
点击查看代码
void solve() {
i64 n;
std::cin >> n;
i64 ans = 0;
for (i64 i = 2, j = 1; i <= std::min(n, 4ll); i *= 2, ++ j) {
i64 l = 1, r = n / i;
while (l < r) {
i64 mid = l + r + 1 >> 1ll;
if ((i128)i * mid * mid <= n) {
l = mid;
} else {
r = mid - 1;
}
}
ans += l;
}
std::cout << ans << "\n";
}
D - Takahashi the Wall Breaker
题意:从\((a, b\))走到\((c, d)\)。每次可以用技能给当前格子一个方向的两格变成道路。问最少放几个技能。
双端队列。
每次枚举队头往四个方向走,代价多0,放队头。然后枚举放技能,代价多1,放队尾。
点击查看代码
void solve() {
int n, m;
std::cin >> n >> m;
std::vector<std::string> s(n);
for (int i = 0; i < n; ++ i) {
std::cin >> s[i];
}
int a, b, c, d;
std::cin >> a >> b >> c >> d;
-- a, -- b, -- c, -- d;
const int inf = 1e9;
std::vector dist(n, std::vector<int>(m, inf));
std::deque<std::pair<int, int>> q;
dist[a][b] = 0;
q.emplace_back(a, b);
const int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
while (q.size()) {
auto [x, y] = q.front(); q.pop_front();
for (int i = 0; i < 4; ++ i) {
int nx = x + dx[i], ny = y + dy[i];
if (nx < 0 || nx >= n || ny < 0 || ny >= m) {
continue;
}
if (s[nx][ny] == '.') {
if (dist[nx][ny] > dist[x][y]) {
dist[nx][ny] = dist[x][y];
q.emplace_front(nx, ny);
}
} else {
if (dist[nx][ny] > dist[x][y] + 1) {
dist[nx][ny] = dist[x][y] + 1;
q.emplace_back(nx, ny);
}
nx += dx[i], ny += dy[i];
if (nx < 0 || nx >= n || ny < 0 || ny >= m) {
continue;
}
if (dist[nx][ny] > dist[x][y] + 1) {
dist[nx][ny] = dist[x][y] + 1;
q.emplace_back(nx, ny);
}
}
}
}
std::cout << dist[c][d] << "\n";
}
E - Ringo's Favorite Numbers 3
题意:多次询问。每次求小于等于\(A\)的最大的\(400\)数。\(400\)数定义为\(p^{k_1}q^{k_2}\)。其中\(pq\)是不一样的质数,\(k_1, k_2\)都是偶数。
考虑预处理。
先进行质数筛。然后暴力跑出所有\(400\)数。当当前乘积大于\(1e12\)就中断。
点击查看代码
std::vector<i64> minp, primes;
void sieve(int n) {
minp.assign(n + 1, 0);
primes.clear();
for (int i = 2; i <= n; ++ i) {
if (minp[i] == 0) {
minp[i] = i;
primes.push_back(i);
}
for (auto p : primes) {
if (i * p > n) {
break;
}
minp[i * p] = p;
if (p == minp[i]) {
break;
}
}
}
}
void solve() {
sieve(1e6);
const i64 N = 1e12;
std::vector<i64> a;
for (int i = 0; i < primes.size() && primes[i] * primes[i] <= N; ++ i) {
for (int j = i + 1; j < primes.size() && (i128)primes[i] * primes[i] * primes[j] * primes[j] <= N; ++ j) {
for (i128 x = primes[i] * primes[i]; x <= N / (primes[j] * primes[j]); x *= primes[i] * primes[i]) {
for (i128 y = primes[j] * primes[j]; x * y <= N; y *= primes[j] * primes[j]) {
a.push_back(x * y);
}
}
}
}
std::ranges::sort(a);
int q;
std::cin >> q;
while (q -- ) {
i64 n;
std::cin >> n;
auto it = std::ranges::upper_bound(a, n);
-- it;
std::cout << *it << "\n";
}
}