Rust for Algorithmic Problem-Solving
Competitive Programming Templates
A competitive programming template combines a fast zero-allocation token scanner, an 8 KiB buffered output writer, modular arithmetic helpers, and multi-testcase orchestration into a single self-contained .rs file that compiles with zero external dependencies on any online judge (Codeforces, AtCoder, LeetCode, Kattis, CSES).
Anatomy of a Single-File Rust Algorithmic Template:
1. `Scanner<'a>` over `io::read_to_string(io::stdin())`
- `.next::<T>()`, `.next_bytes()`, `.next_vec::<T>(n)`
2. `BufWriter<StdoutLock<'static>>`
- Batches all `writeln!(out, ...)` calls into minimal OS syscalls
3. `solve(&mut scan, &mut out)`
- Invoked once (or inside `for _ in 0..t` for multi-testcase problems)
Complete Production-Ready Competitive Programming Template
use std::io::{self, BufWriter, Write};
use std::str::{FromStr, SplitAsciiWhitespace};
pub struct Scanner<'a> {
it: SplitAsciiWhitespace<'a>,
}
impl<'a> Scanner<'a> {
pub fn new(s: &'a str) -> Self {
Self {
it: s.split_ascii_whitespace(),
}
}
#[inline]
pub fn next<T: FromStr>(&mut self) -> T {
self.it
.next()
.expect("EOF")
.parse()
.ok()
.expect("parse error")
}
#[inline]
pub fn next_str(&mut self) -> &'a str {
self.it.next().expect("EOF")
}
#[inline]
pub fn next_bytes(&mut self) -> &'a [u8] {
self.next_str().as_bytes()
}
#[inline]
pub fn next_vec<T: FromStr>(&mut self, n: usize) -> Vec<T> {
(0..n).map(|_| self.next()).collect()
}
}
/// Modular exponentiation: computes `(base^exp) % modulus` in O(log exp) time.
#[inline]
pub const fn mod_pow(mut base: u64, mut exp: u64, modulus: u64) -> u64 {
let mut result = 1u64 % modulus;
base %= modulus;
while exp > 0 {
if (exp & 1) == 1 {
result = ((result as u128 * base as u128) % (modulus as u128)) as u64;
}
base = ((base as u128 * base as u128) % (modulus as u128)) as u64;
exp >>= 1;
}
result
}
/// Greatest Common Divisor (Euclidean algorithm) in O(log(min(a, b))) time.
#[inline]
pub const fn gcd(mut a: u64, mut b: u64) -> u64 {
while b != 0 {
let r = a % b;
a = b;
b = r;
}
a
}
fn solve_test_case(scan: &mut Scanner<'_>, out: &mut impl Write) -> io::Result<()> {
let n: usize = scan.next();
let nums: Vec<u64> = scan.next_vec(n);
let overall_gcd = nums.iter().copied().fold(0u64, gcd);
let mod_ans = mod_pow(overall_gcd, 3, 1_000_000_007);
writeln!(out, "{overall_gcd} {mod_ans}")
}
fn main() -> io::Result<()> {
// In online judge submissions, read from stdin:
// let input = io::read_to_string(io::stdin())?;
let input = "2\n3\n12 18 24\n4\n10 25 35 50\n";
let mut scan = Scanner::new(input);
let stdout = io::stdout();
let mut out = BufWriter::new(stdout.lock());
let t: usize = scan.next();
for _ in 0..t {
solve_test_case(&mut scan, &mut out)?;
}
out.flush()
}
6 216
5 125
Quick Reference of Idiomatic Rust One-Liners for Contests
| Task | Idiomatic Rust Expression |
|---|---|
| Swap two elements in a slice | slice.swap(i, j); |
Update ans = min(ans, cand) |
ans = ans.min(cand); (or ans = ans.max(cand);) |
Print space-separated Vec<i64> |
for (i, x) in v.iter().enumerate() { write!(out, "{x}{}", if i + 1 == v.len() { "\n" } else { " " })?; } |
Safe (a * b) % MOD for 64-bit ints |
((a as u128 * b as u128) % (MOD as u128)) as u64 (Zero 64-bit overflow risk!) |
| Ceiling integer division $\lceil a / b \rceil$ | a.div_ceil(b) (Built into all unsigned integers in modern Rust!) |
| Absolute difference $|a - b|$ | a.abs_diff(b) (Built into all integers; never overflows on signed i64::MIN!) |