Algorithmic Problem Set Solutions: From Basics to Advanced Data Structures
Problem 1: Unique Element Extraction
The task requires reading a sequence of integers and printing each distinct value exactly once in the order of their first appearance. A hash-based container provides an efficient way to track visited numbers.
#include <iostream>
#include <unordered_set>
#include <vector>
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int count;
if (!(std::cin >> count)) return 0;
std::unordered_set<int> observed;
std::vector<int> output_seq;
for (int i = 0; i < count; ++i) {
int val;
std::cin >> val;
if (observed.insert(val).second) {
output_seq.push_back(val);
}
}
for (size_t i = 0; i < output_seq.size(); ++i) {
std::cout << output_seq[i] << (i == output_seq.size() - 1 ? '\n' : ' ');
}
return 0;
}
Problem 2: Precision Percentage Calculation
Given a floating-point number representing a ratio, compute its percentage representation rounded to the nearest integer. Standard rounding functions handle boundary cases correctly.
#include <iostream>
#include <cmath>
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
double input_ratio;
std::cin >> input_ratio;
long long rounded_pct = static_cast<long long>(std::round(input_ratio * 100.0));
std::cout << rounded_pct << '%';
return 0;
}
Problem 3: Magic Square Constant Derivation
For an $n \times n$ normal magic square, the magic constant (sum of any row/column/diagonal) is $\frac{n(n^2+1)}{2}$, and the center cell always holds $\frac{n^2+1}{2}$ for odd $n$. The problem asks to output both values.
#include <iostream>
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
long long dimension;
std::cin >> dimension;
long long center_value = (dimension * dimension + 1) / 2;
long long magic_sum = center_value * dimension;
std::cout << magic_sum << ' ' << center_value << '\n';
return 0;
}
Problem 4: Matrix Transposition and Sorting
The input specifies matrix columns instead of rows. After loading the data into a two-dimensional array, each row must be sorted in ascending order. The final output requires printing the matrix in its transposed form relative to the input orientation.
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int dim;
std::cin >> dim;
std::vector<std::vector<int>> matrix(dim, std::vector<int>(dim));
// Load column-major input
for (int c = 0; c < dim; ++c) {
for (int r = 0; r < dim; ++r) {
std::cin >> matrix[c][r];
}
}
// Sort each row
for (auto& row : matrix) {
std::sort(row.begin(), row.end());
}
// Print transposed back to original axis alignment
for (int c = 0; c < dim; ++c) {
for (int r = 0; r < dim; ++r) {
std::cout << matrix[r][c] << (r == dim - 1 ? '\n' : ' ');
}
}
return 0;
}
Problem 5: Overflow-Safe Fraction Reduction via Prime Factorization
Evaluating expressions like $\frac{\sum a_ib_i}{(\sum a_i)^x + (\sum b_i)^y}$ directly can exceed 64-bit integer limits. By decomposing sums in to prime factors, scaling exponents by powers $x$ and $y$, and systematically cancelling common factors between numerator and denominator terms, we keep intermediate values within long long bounds before applying GCD reduction.
#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>
typedef long long ll;
struct PrimeFactor { ll base; int exponent; };
ll power(ll base, int exp) {
ll res = 1;
while (exp > 0) {
if (exp & 1) res *= base;
base *= base;
exp >>= 1;
}
return res;
}
std::vector<PrimeFactor> get_prime_factors(ll num) {
std::vector<PrimeFactor> factors;
for (ll i = 2; i * i <= num; ++i) {
if (num % i == 0) {
int count = 0;
while (num % i == 0) { num /= i; ++count; }
factors.push_back({i, count});
}
}
if (num > 1) factors.push_back({num, 1});
return factors;
}
std::pair<ll, ll> cancel_fractions(std::vector<PrimeFactor> numer, const std::vector<PrimeFactor>& denom) {
// Merge sorted factors and subtract exponents
for (size_t i = 0, j = 0; i < numer.size() && j < denom.size();) {
if (numer[i].base == denom[j].base) {
numer[i].exponent -= denom[j].exponent;
++i; ++j;
} else if (numer[i].base < denom[j].base) {
++i;
} else {
++j;
}
}
ll n_val = 1, d_val = 1;
for (const auto& p : numer) if (p.exponent > 0) n_val *= power(p.base, p.exponent);
for (const auto& p : denom) if (p.exponent > 0) d_val *= power(p.base, p.exponent);
return {n_val, d_val};
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, x_pow, y_pow;
std::cin >> n >> x_pow >> y_pow;
ll sum_a = 0, sum_b = 0, dot_prod = 0;
std::vector<ll> vals_a(n), vals_b(n);
for(int i=0; i<n; ++i) { std::cin >> vals_a[i]; sum_a += vals_a[i]; }
for(int i=0; i<n; ++i) { std::cin >> vals_b[i]; sum_b += vals_b[i]; dot_prod += vals_a[i]*vals_b[i]; }
auto fac_a = get_prime_factors(sum_a);
auto fac_b = get_prime_factors(sum_b);
auto fac_c = get_prime_factors(dot_prod);
for(auto& p : fac_a) p.exponent *= x_pow;
for(auto& p : fac_b) p.exponent *= y_pow;
auto [xa, xc] = cancel_fractions(fac_a, fac_c);
auto [xb, cc] = cancel_fractions(fac_b, fac_c);
ll numerator = xc * cc;
ll denominator = xa * cc + xb * xc;
ll g = std::gcd(numerator, denominator);
numerator /= g; denominator /= g;
if (denominator == 1) std::cout << numerator << '\n';
else std::cout << numerator << '/' << denominator << '\n';
return 0;
}
Problem 6: Substring Replacement Logic
Scan a source string for a target pattern. Upon detection, increment a counter, append a replacement suffix, and skip ahead to prevent overlapping matches.
#include <iostream>
#include <string>
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::string text, target = "Huade";
std::cin >> text;
int matches = 0;
std::string transformed;
transformed.reserve(text.length() + 100);
for (size_t i = 0; i < text.length(); ) {
if (i + 5 <= text.length() && text.substr(i, 5) == target) {
++matches;
transformed += "Huadeyyds";
i += 5;
} else {
transformed += text[i++];
}
}
if (matches > 0) {
std::cout << matches << '\n' << transformed << '\n';
} else {
std::cout << "0\n";
}
return 0;
}
Problem 7: Wildcard Pattern Matching
Implement naive sliding window matching where a specific character acts as a wildcard compatible with any input character. Iterate through valid starting positions and validate character-by-character compatibility.
#include <iostream>
#include <string>
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::string s, pattern;
std::cin >> s >> pattern;
int occurrences = 0;
size_t plen = pattern.length();
for (size_t i = 0; i <= s.length() - plen; ++i) {
bool consistent = true;
for (size_t k = 0; k < plen; ++k) {
if (pattern[k] != '?' && pattern[k] != s[i+k]) {
consistent = false;
break;
}
}
if (consistent) ++occurrences;
}
std::cout << occurrences << '\n';
return 0;
}
Problem 8: Grid BFS with Diagonal Knight Moves
Perform a breadth-first search on a 2D coordinate plane. Movement rules mimic a chess knight's diagonal jumps $(\pm 2, \pm 2)$. Track distances with a visited matrix initialized to -1.
#include <iostream>
#include <vector>
#include <queue>
#include <tuple>
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int rows, cols, sr, sc;
std::cin >> rows >> cols >> sr >> sc;
std::vector<std::vector<int>> dist(rows + 1, std::vector<int>(cols + 1, -1));
std::queue<std::pair<int,int>> q;
dist[sr][sc] = 0;
q.push({sr, sc});
int dr[] = {2, 2, -2, -2};
int dc[] = {2, -2, 2, -2};
while (!q.empty()) {
auto [cr, cc] = q.front();
q.pop();
for (int k = 0; k < 4; ++k) {
int nr = cr + dr[k];
int nc = cc + dc[k];
if (nr >= 1 && nr <= rows && nc >= 1 && nc <= cols && dist[nr][nc] == -1) {
dist[nr][nc] = dist[cr][cc] + 1;
q.push({nr, nc});
}
}
}
for (int i = 1; i <= rows; ++i) {
for (int j = 1; j <= cols; ++j) {
std::cout << dist[i][j] << (j == cols ? '\n' : ' ');
}
}
return 0;
}
Problem 9: Queue-Based Josephus Simulation
A variant of the classic elimination game. Individuals are arranged in a circular queue. Every $(k+1)$-th person is eliminated (printed), while others are rotated back to the end until one remains.
#include <iostream>
#include <queue>
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, k;
std::cin >> n >> k;
std::queue<int> circle;
for (int i = 0; i < n; ++i) {
int val;
std::cin >> val;
circle.push(val);
}
int step_counter = 0;
while (circle.size() > 1) {
if (step_counter % (k + 1) == 0) {
std::cout << circle.front() << ' ';
} else {
circle.push(circle.front());
}
++step_counter;
circle.pop();
}
return 0;
}
Problem 10: Geometric Volume Computation
Calculate a composite geometric volume involving conic and cylindrical components. Apply precise floating-point arithmetic and standard formatting for two decimal places.
#include <iostream>
#include <iomanip>
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
double R, r, H, h;
std::cin >> R >> r >> H >> h;
constexpr double PI = 3.14159265358979323846;
double term_conic = 2.0 * PI * R * R * R;
double term_cylindrical = PI * (H * R * R - h * r * r);
double total_volume = (term_conic + term_cylindrical) / 3.0;
std::cout << std::fixed << std::setprecision(2) << total_volume << '\n';
return 0;
}
Problem 11: Segment Tree for Lexicographical Range Queries
Dynamic string manipulation requiring point updates and range maximum queries. A recursive segment tree maintains lexicographical ordering across partitions, enabling $O(\log N)$ operations.
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
int n, q;
std::vector<std::string> dataset;
std::vector<std::string> seg_tree;
void build(int node, int l, int r) {
if (l == r) {
seg_tree[node] = dataset[l];
return;
}
int mid = (l + r) / 2;
build(2 * node, l, mid);
build(2 * node + 1, mid + 1, r);
seg_tree[node] = std::max(seg_tree[2 * node], seg_tree[2 * node + 1]);
}
void modify(int node, int l, int r, int idx, const std::string& val) {
if (l == r) {
seg_tree[node] = val;
return;
}
int mid = (l + r) / 2;
if (idx <= mid) modify(2 * node, l, mid, idx, val);
else modify(2 * node + 1, mid + 1, r, idx, val);
seg_tree[node] = std::max(seg_tree[2 * node], seg_tree[2 * node + 1]);
}
std::string query(int node, int l, int r, int ql, int qr) {
if (ql > r || qr < l) return "";
if (ql <= l && r <= qr) return seg_tree[node];
int mid = (l + r) / 2;
return std::max(query(2 * node, l, mid, ql, qr),
query(2 * node + 1, mid + 1, r, ql, qr));
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cin >> n >> q;
dataset.resize(n + 1);
seg_tree.resize(4 * (n + 1));
for (int i = 1; i <= n; ++i) std::cin >> dataset[i];
build(1, 1, n);
while (q--) {
char type;
std::cin >> type;
if (type == 'Q') {
int left, right;
std::cin >> left >> right;
std::string res = query(1, 1, n, left, right);
std::cout << (res.empty() ? "null" : res) << '\n';
} else {
int pos;
std::string new_val;
std::cin >> pos >> new_val;
modify(1, 1, n, pos, new_val);
}
}
return 0;
}