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";
	}
}
posted @ 2025-04-05 21:40  maburb  阅读(299)  评论(0)    收藏  举报