アルゴリズムやデータ構造ごとに問題を分類する
タイトルのまんまです。アルゴリズムやデータ構造ごとに、そのアルゴリズムを使って解けそうな問題をリストアップします。基本的に私が解いた問題から載せていくので、最初の内は簡単なものばかりで数も少ないです。
目次
アルゴリズム | データ構造 | その他 |
---|---|---|
全探索-5問 | 累積和 | 文字列操作 |
工夫のいる全探索-3問 | いもす法 | 最小公倍数 |
バブルソート | スタック-8問 | 回文判定 |
約数列挙 | HashSet | n進数 |
二分探索 | HashMap | 周期性 |
bit全探索 | BTreeSet | 後から帳尻合わせる系 |
再帰関数 | BTreeMap | |
メモ化再帰 | ||
深さ優先探索 | ||
幅優先探索-18問 | ||
ユークリッドの互除法 | ||
ランレングス圧縮 | ||
動的計画法 | ||
貪欲法 | ||
尺取り法 |
アルゴリズム
全探索-5問
アルゴリズムの基本というか、考え得るパターンを全て試していく方法です。B問題までであれば全探索で間に合うことが多いです。
ABC393 B - A..B..C
B - A..B..C(Difficulty : 44)
コード例を見る
// https://atcoder.jp/contests/abc393/tasks/abc393_b
fn run(s: &str) -> usize {
let chars: Vec<char> = s.chars().collect();
let mut ans = 0;
for i in 0..s.len() {
for j in i+1..s.len() {
for k in j+1..s.len() {
if j - i == k - j {
if chars[i] == 'A' && chars[j] == 'B' && chars[k] == 'C' {
ans += 1;
}
}
}
}
}
ans
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(&'static str, usize);
#[test]
fn test() {
let tests = [
TestCase("AABCC", 2),
TestCase("ARC", 0),
TestCase("AABAAABBAEDCCCD", 4),
];
for TestCase(s, expected) in tests {
assert_eq!(run(s), expected);
}
}
}
ABC331 B - Buy One Carton of Milk
B - Buy One Carton of Milk(Difficulty : 182)
コード例を見る
// https://atcoder.jp/contests/abc331/tasks/abc331_b
fn run(n: usize, s: usize, m: usize, l: usize) -> usize {
let mut ans = std::usize::MAX;
for i in 0..=100 {
for j in 0..=100 {
for k in 0..=100 {
if i*6 + j*8 + k*12 >= n {
ans = ans.min(i*s + j*m + k*l);
}
}
}
}
ans
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(300, run(16, 120, 150, 200));
assert_eq!(10, run(10, 100, 50, 10));
assert_eq!(10000, run(99, 600, 800, 1200));
}
}
ABC224 C - Triangle?
C - Triangle?(Difficulty : 301)
コード例を見る
// https://atcoder.jp/contests/abc224/tasks/abc224_c
fn run(n: usize, xy: Vec<(isize, isize)>) -> usize {
let mut ans = 0;
for i in 0..n {
for j in i+1..n {
for k in j+1..n {
if (xy[j].0 - xy[i].0)*(xy[k].1 - xy[i].1) - (xy[k].0 - xy[i].0)*(xy[j].1 - xy[i].1) != 0 {
ans += 1;
}
}
}
}
ans
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, Vec<(isize, isize)>, usize);
#[test]
fn test() {
let tests = [
TestCase(4, vec![(0, 1), (1, 3), (1, 1), (-1, -1)], 3),
TestCase(20, vec![(224, 433), (987654321, 987654321), (2, 0), (6, 4), (314159265, 358979323), (0, 0), (-123456789, 123456789), (-1000000000, 1000000000), (124, 233), (9, -6), (-4, 0), (9, 5), (-7, 3), (333333333, -333333333), (-9, -1), (7, -10), (-1, 5), (324, 633), (1000000000, -1000000000), (20, 0)], 1124),
];
for TestCase(n, xy, expected) in tests {
assert_eq!(run(n, xy), expected);
}
}
}
ABC391 B - Seek Grid
B - Seek Grid(Difficulty : -)
4重forループですが、M ≦ N ≦ 50なので間に合います。
コード例を見る
// https://atcoder.jp/contests/abc391/tasks/abc391_b
fn run(n: usize, m: usize, s: Vec<&str>, t: Vec<&str>) -> (usize, usize) {
let vec_s: Vec<Vec<char>> = s.into_iter().map(|s| s.chars().collect()).collect();
let vec_t: Vec<Vec<char>> = t.into_iter().map(|s| s.chars().collect()).collect();
for i in 0..=n-m {
for j in 0..=n-m {
let mut flag = true;
for k in 0..m {
for l in 0..m {
if vec_s[i+k][j+l] != vec_t[k][l] {
flag = false;
}
}
}
if flag {
return (i+1, j+1);
}
}
}
unreachable!();
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, Vec<&'static str>, Vec<&'static str>, (usize, usize));
#[test]
fn test() {
let tests = [
TestCase(3, 2, vec!["#.#", "..#", "##."], vec![".#", "#."], (2, 2)),
TestCase(2, 1, vec!["#.", "##"], vec!["."], (1, 2)),
];
for TestCase(n, m, s, t, expected) in tests {
assert_eq!(run(n, m, s, t), expected);
}
}
}
ABC201 C - Secret Number
C - Secret Number(Difficulty : 439)
コード例を見る
// https://atcoder.jp/contests/abc201/tasks/abc201_c
fn run(s: &str) -> usize {
let chars: Vec<char> = s.chars().collect();
let mut ans = 0;
for i in 0..10000 {
let str = format!("{:04}", i);
let mut flags = vec![false; 10];
for c in str.chars() {
let i = c.to_digit(10).unwrap();
flags[i as usize] = true;
}
let mut flag = true;
for j in 0..10 {
if chars[j] == 'o' && flags[j] == false {
flag = false;
break;
}
if chars[j] == 'x' && flags[j] {
flag = false;
break;
}
}
if flag {
ans += 1;
}
}
ans
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(&'static str, usize);
#[test]
fn test() {
let tests = [
TestCase("ooo???xxxx", 108),
TestCase("o?oo?oxoxo", 0),
TestCase("xxxxx?xxxo", 15),
];
for TestCase(s, expected) in tests {
assert_eq!(run(s), expected);
}
}
}
工夫のいる全探索-3問
とりえるパターンを全て試すとTLEになるので、何らかの工夫を凝らして計算量を減らすタイプの全探索です。
JOI 2023/2024 二次予選 A - カードゲーム 2 (Card Game 2)
A - カードゲーム 2 (Card Game 2)(Difficultyなし)
コード例を見る
// https://atcoder.jp/contests/joi2024yo2/tasks/joi2024_yo2_a
fn run(_n: usize, a: Vec<usize>) -> &'static str {
let mut vec = vec![false; 200_000];
for i in a {
vec[i-1] = true;
}
for i in 0..200_000-3 {
if vec[i] == true && vec[i+3] == true && vec[i+6] == true {
return "Yes";
}
}
"No"
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, Vec<usize>, &'static str);
#[test]
fn test() {
let tests = [
TestCase(3, vec![2, 5, 8], "Yes"),
TestCase(4, vec![1, 4, 6, 4], "No"),
TestCase(8, vec![9, 8, 11, 1, 1, 6, 10, 4], "No"),
TestCase(20, vec![2, 15, 4, 30, 6, 8, 11, 27, 14, 3, 16, 26, 19, 2, 23, 21, 18, 13, 28, 6], "Yes"),
];
for TestCase(n, a, expected) in tests {
assert_eq!(run(n, a), expected);
}
}
}
JOI 2022/2023 二次予選 A - 年齢の差 (Age Difference)
A - 年齢の差 (Age Difference)(Difficultyなし)
コード例を見る
// https://atcoder.jp/contests/joi2023yo2/tasks/joi2023_yo2_a
use itertools::Itertools;
fn run(_n: usize, a: Vec<isize>) -> Vec<usize> {
let vec: Vec<isize> = a.clone().into_iter().sorted().collect();
let min = vec.iter().min().unwrap();
let max = vec.iter().max().unwrap();
a.into_iter()
.map(|i| {
std::cmp::max((i - *min).abs(), (*max - i).abs()) as usize
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, Vec<isize>, Vec<usize>);
#[test]
fn test() {
let tests = [
TestCase(3, vec![13, 15, 20], vec![7, 5, 7]),
TestCase(2, vec![100, 100], vec![0, 0]),
TestCase(10, vec![440894064, 101089692, 556439322, 34369336, 98417847, 216265879, 623843484, 554560874, 247445405, 718003331], vec![406524728, 616913639, 522069986, 683633995, 619585484, 501737452, 589474148, 520191538, 470557926, 683633995]),
];
for TestCase(n, a, expected) in tests {
assert_eq!(run(n, a), expected);
}
}
}
ABC085 C - Otoshidama
C - Otoshidama(Difficulty : 584)
コード例を見る
// https://atcoder.jp/contests/abc085/tasks/abc085_c
fn run(n: isize, y: isize) -> Vec<isize> {
for i in 0..=n {
for j in 0..=n {
let k = n - i - j;
if k < 0 || n < k {
continue;
}
if i * 10000 + j * 5000 + k * 1000 == y {
return vec![i, j, k];
}
}
}
vec![-1, -1, -1]
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(isize, isize, Vec<isize>);
#[test]
fn test() {
let tests = [
TestCase(9, 45000, vec![4, 0, 5]),
TestCase(20, 196000, vec![-1, -1, -1]),
TestCase(1000, 1234000, vec![2, 54, 944]),
TestCase(2000, 20000000, vec![2000, 0, 0]),
];
for TestCase(n, y, expected) in tests {
assert_eq!(run(n, y), expected);
}
}
}
バブルソート
ABC264 D - “redocta”.swap(i,i+1)
D - “redocta”.swap(i,i+1)(Difficulty : 414)
コード例を見る
// https://atcoder.jp/contests/abc264/tasks/abc264_d
fn run(s: &str) -> usize {
let mut ans = 0;
let mut vec: Vec<usize> = s.chars()
.map(|c| {
match c {
'a' => 0,
't' => 1,
'c' => 2,
'o' => 3,
'd' => 4,
'e' => 5,
'r' => 6,
_ => unreachable!(),
}
})
.collect();
for i in 0..7 {
let mut flag = true;
for j in 0..7-i-1 {
if vec[j] > vec[j+1] {
vec.swap(j, j+1);
ans += 1;
flag = false;
}
}
if flag == true {
return ans;
}
}
ans
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(&'static str, usize);
#[test]
fn test() {
let tests = [
TestCase("catredo", 8),
TestCase("atcoder", 0),
TestCase("redocta", 21),
];
for TestCase(s, expected) in tests {
assert_eq!(run(s), expected);
}
}
}
二分探索
ABC388 C - Various Kagamimochi
C - Various Kagamimochi(Difficulty : 211)
コード例を見る
use std::cmp::Ordering;
fn upper_bound<T: Ord>(vec: &[T], value: T) -> usize {
vec.binary_search_by(|x| {
if *x <= value {
Ordering::Less
} else {
Ordering::Greater
}
})
.err()
.unwrap()
}
fn run(_n: usize, a: Vec<usize>) -> usize {
a.iter()
.map(|x| {
upper_bound(&a, x/2)
})
.sum()
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, Vec<usize>, usize);
#[test]
fn test() {
let tests = [
TestCase(6, vec![2, 3, 4, 4, 7, 10], 8),
TestCase(3, vec![387, 388, 389], 0),
TestCase(32, vec![1, 2, 4, 5, 8, 10, 12, 16, 19, 25, 33, 40, 50, 64, 87, 101, 149, 175, 202, 211, 278, 314, 355, 405, 412, 420, 442, 481, 512, 582, 600, 641], 388),
];
for TestCase(n, a, expected) in tests {
assert_eq!(run(n, a), expected);
}
}
}
ABC365 C - Transportation Expenses
C - Transportation Expenses(Difficulty : 269)
コード例を見る
// https://atcoder.jp/contests/abc365/tasks/abc365_c
use std::cmp::min;
fn check(a: &Vec<usize>, x: usize, m: usize) -> bool {
let mut total = 0;
for n in a.iter() {
total += min(n, &x);
}
total <= m
}
fn run(_n: usize, m: usize, a: Vec<usize>) -> String {
let sum: usize = a.iter().sum();
if sum <= m {
return "infinite".to_string();
}
let mut l = 0;
let mut r = std::usize::MAX;
while l+1 < r {
let tmp = (l+r)/2;
if check(&a, tmp, m) == true {
l = tmp;
} else {
r = tmp;
}
}
l.to_string()
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, Vec<usize>, &'static str);
#[test]
fn test() {
let tests = [
TestCase(4, 8, vec![1, 3, 2, 4], "2"),
TestCase(3, 20, vec![5, 3, 2], "infinite"),
TestCase(10, 23, vec![2, 5, 6, 5, 2, 1, 7, 9, 7, 2], "2"),
];
for TestCase(n, m, a, expected) in tests {
assert_eq!(run(n, m, a), expected);
}
}
}
約数列挙
ABC180 C - Cream puff
C - Cream puff(Difficulty : 142)
コード例を見る
// https://atcoder.jp/contests/abc180/tasks/abc180_c
fn run(n: usize) -> Vec<usize> {
let mut ans = Vec::new();
for i in 1..=(n as f64).sqrt() as usize {
if n % i == 0 {
let j = n / i;
ans.push(i);
if i != j {
ans.push(j);
}
}
}
ans.sort();
ans
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(vec![1, 2, 3, 6], run(6));
assert_eq!(vec![1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24, 30, 36, 40, 45, 48, 60, 72, 80, 90, 120, 144, 180, 240, 360, 720], run(720));
assert_eq!(vec![1, 1000000007], run(1000000007));
assert_eq!(vec![1], run(1));
}
}
bit全探索
ARC105 A - Fourtune Cookies
A - Fourtune Cookies(Difficulty : 34)
bit全探索の練習にはぴったりだと思います。
コード例を見る
// https://atcoder.jp/contests/arc105/tasks/arc105_a
fn run(a: usize, b: usize, c: usize, d: usize) -> String {
let vec = vec![a, b, c, d];
for bit in 0..(1 << 4) {
let mut eat = 0;
let mut rest = 0;
for i in 0..4 {
if bit & (1 << i) != 0 {
eat += vec[i];
} else {
rest += vec[i];
}
}
if eat == rest {
return String::from("Yes");
}
}
String::from("No")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(String::from("Yes"), run(1, 3, 2, 4));
assert_eq!(String::from("No"), run(1, 2, 4, 8));
assert_eq!(String::from("Yes"), run(1, 1, 1, 1));
assert_eq!(String::from("Yes"), run(1, 100, 50, 51));
assert_eq!(String::from("Yes"), run(2, 100, 48, 50));
assert_eq!(String::from("Yes"), run(63214004, 4741111, 4654151, 63300964));
assert_eq!(String::from("No"), run(4630987, 9157337, 18793476, 5005153));
assert_eq!(String::from("No"), run(93407609, 30427494, 56229544, 81174201));
}
}
ARC025 A - ゴールドラッシュ
A - ゴールドラッシュ(🧪 Difficulty : 120)
コード例を見る
// https://atcoder.jp/contests/arc025/tasks/arc025_1
fn run(dd: Vec<usize>, jj: Vec<usize>) -> usize {
let mut ans = 0;
for bit in 0..(1 << dd.len()) {
let mut total = 0;
for i in 0..dd.len() {
if bit & (1 << i) != 0 {
total += dd[i];
} else {
total += jj[i];
}
}
ans = ans.max(total);
}
ans
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(33, run(vec![4, 2, 0, 5, 6, 2, 5], vec![6, 1, 4, 3, 6, 4, 6]));
assert_eq!(35, run(vec![1, 2, 3, 4, 5, 6, 7], vec![2, 3, 4, 5, 6, 7, 8]));
assert_eq!(0, run(vec![0, 0, 0, 0, 0, 0, 0], vec![0, 0, 0, 0, 0, 0, 0]));
assert_eq!(793, run(vec![8, 3, 0, 2, 5, 25, 252], vec![252, 252, 2, 5, 2, 5, 2]));
}
}
ABC374 C - Separated Lunch
C - Separated Lunch(Difficulty : 226)
コード例を見る
// https://atcoder.jp/contests/abc374/tasks/abc374_c
use std::cmp::{min, max};
fn run(n: usize, k: Vec<usize>) -> usize {
let mut ans = std::usize::MAX;
for bit in 0..(1 << n) {
let mut left = 0;
let mut right = 0;
for i in 0..n {
if bit & 1 << i != 0 {
left += k[i];
} else {
right += k[i];
}
}
ans = min(ans, max(left ,right));
}
ans
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, Vec<usize>, usize);
#[test]
fn test() {
let tests = [
TestCase(5, vec![2, 3, 5, 10, 12], 17),
TestCase(2, vec![1, 1], 1),
TestCase(6, vec![22, 25, 26, 45, 22, 31], 89),
];
for TestCase(n, k, expected) in tests {
assert_eq!(run(n, k), expected);
}
}
}
ABC182 C - To 3
C - To 3(Difficulty : 292)
コード例を見る
// https://atcoder.jp/contests/abc182/tasks/abc182_c
fn run(n: usize) -> i32 {
// 1個も消さずに3で割り切れる場合
if n % 3 == 0 {
return 0;
}
let mut ans = std::i32::MAX;
// 各桁をVec<i32>に格納
let vec: Vec<i32> = n.to_string().chars().map(|c| c.to_digit(10).unwrap() as i32).collect();
for bit in 1..(1 << vec.len()) {
// 各桁の合計数
let mut num = 0;
// 数値を消した数
let mut count = 0;
for i in 0..vec.len() {
if bit & (1 << i) != 0 {
num += vec[i] * 10_i32.pow(i as u32);
count += 1;
}
}
if num % 3 == 0 {
ans = ans.min(count);
}
}
if ans == std::i32::MAX {
-1
} else {
ans
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(1, run(35));
assert_eq!(0, run(369));
assert_eq!(1, run(6227384));
assert_eq!(-1, run(11));
}
}
ABC079 C - Train Ticket
C - Train Ticket(Difficulty : 337)
コード例を見る
// https://atcoder.jp/contests/abc079/tasks/abc079_c
fn run(s: &str) -> String {
let nums: Vec<i32> = s.chars().map(|c| c.to_digit(10).unwrap() as i32).collect();
for bit in 0..(1 << 3) {
// +、-を格納していくVec<char>
let mut ans = Vec::new();
// 各数値を+-した合計値
let mut sum = nums[0];
for i in 0..3 {
if bit & (1 << i) != 0 {
sum += nums[i+1];
ans.push('+');
} else {
sum -= nums[i+1];
ans.push('-');
}
}
if sum == 7 {
return format!("{}{}{}{}{}{}{}=7", nums[0], ans[0], nums[1], ans[1], nums[2], ans[2], nums[3]);
}
}
unreachable!();
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(String::from("1+2+2+2=7"), run("1222"));
assert_eq!(String::from("0-2+9-0=7"), run("0290"));
assert_eq!(String::from("3+2+4-2=7"), run("3242"));
}
}
ARC061 C - たくさんの数式
C - たくさんの数式(Difficulty : 1089)
コード例を見る
// https://atcoder.jp/contests/abc045/tasks/arc061_a
fn run(s: &str) -> usize {
let len = s.len();
let chars: Vec<char> = s.chars().collect();
let mut ans = 0;
for bit in 0..(1 << len-1) {
let mut current = chars[0].to_string();
let mut sum = 0;
for i in 0..(len-1) {
if bit & (1 << i) != 0 {
current.push(chars[i+1]);
} else {
sum += current.parse::<usize>().unwrap();
current = chars[i+1].to_string();
}
}
sum += current.parse::<usize>().unwrap();
ans+= sum;
}
ans
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(&'static str, usize);
#[test]
fn test() {
let tests = [
TestCase("125", 176),
TestCase("9999999999", 12656242944),
];
for TestCase(s, expected) in tests {
assert_eq!(run(s), expected);
}
}
}
再帰関数
ABC229 B - Hard Calculation
B - Hard Calculation(Difficulty : 42)
コード例を見る
// https://atcoder.jp/contests/abc229/tasks/abc229_b
fn calc(a: usize, b: usize) -> bool {
if a == 0 || b == 0 {
true
} else if a%10 + b %10 >= 10 {
false
} else {
calc(a/10, b/10)
}
}
fn run(a: usize, b: usize) -> String {
if calc(a, b) == true {
String::from("Easy")
} else {
String::from("Hard")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(String::from("Hard"), run(229, 390));
assert_eq!(String::from("Easy"), run(123456789, 9876543210));
}
}
ABC248 B - Slimes
B - Slimes(Difficulty : 41)
コード例を見る
// https://atcoder.jp/contests/abc248/tasks/abc248_b
fn calc(count: usize, a: usize, b: usize, k: usize) -> usize {
if a >= b {
count
} else {
calc(count+1, a*k, b, k)
}
}
fn run(a: usize, b: usize, k: usize) -> usize {
calc(0, a, b, k)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(2, run(1, 4, 2));
assert_eq!(0, run(7, 7, 10));
assert_eq!(6, run(31, 415926, 5));
assert_eq!(1, run(158260522, 200224287, 10));
assert_eq!(30, run(1, 1000000000, 2));
assert_eq!(1, run(999999999, 1000000000, 500000000));
assert_eq!(29, run(1, 536870912, 2));
}
}
ABC083 C - Multiple Gift
C - Multiple Gift(Difficulty : 392)
コード例を見る
// https://atcoder.jp/contests/abc083/tasks/arc088_a
fn calc(n: usize, y: usize, count: usize) -> usize {
if n > y {
count
} else {
calc(n*2, y, count+1)
}
}
fn run(x: usize, y: usize) -> usize {
calc(x, y, 0)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(3, run(3, 20));
assert_eq!(3, run(25, 100));
assert_eq!(31, run(314159265, 358979323846264338));
}
}
ABC100 C - *3 or /2
C - *3 or /2(Difficulty : 327)
コード例を見る
fn calc(num: usize, count: usize) -> usize {
if num % 2 != 0 {
count
} else {
calc(num/2, count+1)
}
}
fn run(_n: usize, a: vec<usize>) -> usize {
a.iter()
.map(|num| {
// 各要素が2で何回割り切れるかを合計
calc(*num, 0)
})
.sum()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(3, run2(3, vec![5, 2, 4]));
assert_eq!(0, run2(4, vec![631, 577, 243, 199]));
assert_eq!(39, run2(10, vec![2184, 2126, 1721, 1800, 1024, 2528, 3360, 1945, 1280, 1776]));
}
}
ABC029 C - Brute-force Attack
C - Brute-force Attack(Difficulty : 584)
コード例を見る
// https://atcoder.jp/contests/abc029/tasks/abc029_c
fn func(n: usize, s: String, vec: &mut Vec<String>) -> Vec<String> {
if n == 0 {
vec.push(s);
vec.clone()
} else {
for c in ["a", "b", "c"].iter() {
func(n - 1, s.clone() + &c.to_string(), vec);
}
vec.clone()
}
}
fn run(n: usize) -> Vec<String> {
func(n, "".to_string(), &mut Vec::new())
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, Vec<&'static str>);
#[test]
fn test() {
let tests = [
TestCase(1, vec!["a", "b", "c"]),
TestCase(2, vec!["aa", "ab", "ac", "ba", "bb", "bc", "ca", "cb", "cc"]),
];
for TestCase(n, expected) in tests {
assert_eq!(run(n), expected);
}
}
}
メモ化再帰
ABC275 D - Yet Another Recursive Function
D - Yet Another Recursive Function(Difficulty : 606)
コード例を見る
// すぐ書く
ABC340 C - Divide and Divide
C - Divide and Divide(Difficulty : 528)
コード例を見る
// https://atcoder.jp/contests/abc340/tasks/abc340_c
use std::collections::HashMap;
fn calc(n: usize, h: &mut HashMap<usize, usize>) -> usize {
if n < 2 {
return 0;
}
if let Some(x) = h.get(&n) {
return *x;
}
let a = n/2;
let b = if n % 2 == 0 { n / 2 } else { n / 2 + 1 };
let num = n + calc(a, h) + calc(b, h);
h.entry(n).or_insert(num);
return num;
}
fn run(n: usize) -> usize {
let mut hash_map: HashMap<usize, usize> = HashMap::new();
calc(n, &mut hash_map)
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize);
#[test]
fn test() {
let tests = [
TestCase(3, 5),
TestCase(340, 2888),
TestCase(100000000000000000, 5655884811924144128),
];
for TestCase(n, expected) in tests {
assert_eq!(run(n), expected);
}
}
}
深さ優先探索
ATC001 A - 深さ優先探索
A - 深さ優先探索(Difficultyなし)
コード例を見る
// https://atcoder.jp/contests/atc001/tasks/dfs_a
fn check(h: isize, w: isize, i: isize, j: isize) -> bool {
i < 0 || j < 0 || i >= h || j >= w
}
fn dfs(vec: &Vec<Vec<char>>, seen: &mut Vec<Vec<bool>>, cur_i: usize, cur_j: usize) {
seen[cur_i][cur_j] = true;
let dx = [0, 1, 0, -1];
let dy = [1, 0, -1, 0];
for i in 0..4 {
if check(vec.len() as isize, vec[0].len() as isize, cur_i as isize + dx[i], cur_j as isize + dy[i]) {
continue;
}
let next_i = (cur_i as isize + dx[i]) as usize;
let next_j = (cur_j as isize + dy[i]) as usize;
if vec[next_i][next_j] == '#' || seen[next_i][next_j] {
continue;
}
dfs(&vec, seen, next_i, next_j)
}
}
fn run(h: usize, w: usize, c: Vec<&str>) -> &'static str {
let vec: Vec<Vec<char>> = c.into_iter().map(|str| str.chars().collect()).collect();
let mut start = (0, 0);
let mut end = (0, 0);
for i in 0..h {
for j in 0..w {
if vec[i][j] == 's' {
start = (i, j);
}
if vec[i][j] == 'g' {
end = (i, j);
}
}
}
let mut seen = vec![vec![false; w]; h];
dfs(&vec, &mut seen, start.0, start.1);
if seen[end.0][end.1] {
"Yes"
} else {
"No"
}
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, Vec<&'static str>, &'static str);
#[test]
fn test() {
let tests = [
TestCase(4, 5, vec!["s####", "....#", "#####", "#...g"], "No"),
TestCase(4, 4, vec!["...s", "....", "....", ".g.."], "Yes"),
];
for TestCase(h, w, c, expected) in tests {
assert_eq!(run(h, w, c), expected);
}
}
}
ABC277 C - Ladder Takahashi
C - Ladder Takahashi(Difficulty : 540)
コード例を見る
// https://atcoder.jp/contests/abc277/tasks/abc277_c
use std::collections::{HashMap, HashSet};
fn dfs(current: usize, seen: &mut HashSet<usize>, graph: &HashMap<usize, Vec<usize>>) -> usize {
let mut ans = current;
seen.insert(ans);
for tmp in graph.get(¤t).unwrap() {
if seen.contains(tmp) {
continue;
}
ans = ans.max(dfs(*tmp, seen, graph));
}
ans
}
fn run(_n: usize, ab: Vec<(usize, usize)>) -> usize {
let mut hash_map: HashMap<usize, Vec<usize>> = HashMap::new();
for &(a, b) in ab.iter() {
hash_map.entry(a).or_insert_with(|| Vec::new()).push(b);
hash_map.entry(b).or_insert_with(|| Vec::new()).push(a);
}
// 1階からどこにも行けなかったら1を返す
let Some(_) = hash_map.get(&1) else {
return 1;
};
dfs(1, &mut HashSet::new(), &hash_map)
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, Vec<(usize, usize)>, usize);
#[test]
fn test() {
let tests = [
TestCase(4, vec![(1, 4), (4, 3), (4, 10), (8, 3), (1, 2)], 10),
TestCase(6, vec![(1, 3), (1, 5), (1, 12), (3, 5), (3, 12), (5, 12)], 12),
TestCase(3, vec![(500000000, 600000000), (600000000, 700000000), (700000000, 800000000)], 1),
];
for TestCase(n, ab, expected) in tests {
assert_eq!(run(n, ab), expected);
}
}
}
ABC396 D - Minimum XOR Path
D - Minimum XOR Path(Difficulty : 601)
コード例を見る
// https://atcoder.jp/contests/abc396/tasks/abc396_d
use std::collections::HashMap;
fn dfs(
n: usize,
hash_map: &HashMap<usize, Vec<(usize, usize)>>,
seen: &mut Vec<bool>,
cur: usize,
xor: usize,
ans: &mut usize
) {
seen[cur] = true;
let Some(next) = hash_map.get(&cur) else {
return;
};
for (w, next) in next {
if *next == n {
*ans = (*ans).min(w ^ xor);
continue;
}
if seen[*next] {
continue;
}
dfs(n, hash_map, seen, *next, w ^ xor, ans)
}
seen[cur] = false;
}
fn run(n: usize, _m: usize, uvw: Vec<(usize, usize, usize)>) -> usize {
let mut hash_map = HashMap::new();
for (u, v, w) in uvw {
hash_map.entry(u).or_insert_with(|| Vec::new()).push((w, v));
hash_map.entry(v).or_insert_with(|| Vec::new()).push((w, u));
}
let mut seen = vec![false; n+1];
let mut ans = std::usize::MAX;
dfs(n, &hash_map, &mut seen, 1, 0, &mut ans);
ans
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, Vec<(usize, usize, usize)>, usize);
#[test]
fn test() {
let tests = [
TestCase(4, 4, vec![(1, 2, 3), (2, 4, 5), (1, 3, 4), (3, 4, 7)], 3),
TestCase(4, 3, vec![(1, 2, 1), (2, 3, 2), (3, 4, 4)], 7),
TestCase(7, 10, vec![(1, 2, 726259430069220777), (1, 4, 988687862609183408), (1, 5, 298079271598409137), (1, 6, 920499328385871537), (1, 7, 763940148194103497), (2, 4, 382710956291350101), (3, 4, 770341659133285654), (3, 5, 422036395078103425), (3, 6, 472678770470637382), (5, 7, 938201660808593198)], 186751192333709144),
];
for TestCase(n, m, uvw, expected) in tests {
assert_eq!(run(n, m, uvw), expected);
}
}
}
幅優先探索-18問
BFS (幅優先探索) 超入門! 〜 キューを鮮やかに使いこなす 〜
ABC007 C - 幅優先探索
C - 幅優先探索(🧪 Difficulty : 1024)
そのまんまの問題です。
コード例を見る
// https://atcoder.jp/contests/atc002/tasks/abc007_3
use std::collections::VecDeque;
fn run(r: usize, c: usize, s: (usize, usize), g: (usize, usize), v: Vec<&str>) -> usize {
let vec: Vec<Vec<char>> = v.into_iter().map(|c| c.chars().collect()).collect();
let mut graph = vec![vec![-1; c]; r];
let mut queue = VecDeque::new();
graph[s.0-1][s.1-1] = 0;
queue.push_back((s.0-1, s.1-1));
let dx = [0, -1, 0, 1];
let dy = [-1, 0, 1, 0];
while queue.len() > 0 {
let cur = queue.pop_front().unwrap();
for i in 0..4 {
let h = (cur.0 as isize + dx[i]) as usize;
let w = (cur.1 as isize + dy[i]) as usize;
if vec[h][w] == '#' || graph[h][w] != -1 {
continue;
}
graph[h][w] = graph[cur.0][cur.1] + 1;
queue.push_back((h, w));
}
}
graph[g.0-1][g.1-1] as usize
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, (usize, usize), (usize, usize), Vec<&'static str>, usize);
#[test]
fn test() {
let tests = [
TestCase(7, 8, (2, 2), (4, 5), vec!["########", "#......#", "#.######", "#..#...#", "#..##..#", "##.....#", "########"], 11),
TestCase(5, 8, (2, 2), (2, 4), vec!["########", "#.#....#", "#.###..#", "#......#", "########"], 10),
];
for TestCase(r, c, s, g, v, expected) in tests {
assert_eq!(run(r, c, s, g, v), expected);
}
}
}
競技プログラミングの鉄則 A63 - Shortest Path 1
Shortest Path 1(Difficultyなし)
コード例を見る
// https://atcoder.jp/contests/tessoku-book/tasks/math_and_algorithm_an
use std::collections::{HashMap, VecDeque};
fn run(n: usize, _m: usize, ab: Vec<(usize, usize)>) -> Vec<isize> {
let mut hash_map = HashMap::new();
for (a, b) in ab {
hash_map.entry(a-1).or_insert_with(Vec::new).push(b-1);
hash_map.entry(b-1).or_insert_with(Vec::new).push(a-1);
}
let mut graph = vec![-1; n];
graph[0] = 0;
let mut queue = VecDeque::new();
queue.push_back(0);
while let Some(cur) = queue.pop_front() {
let Some(next) = hash_map.get(&cur) else {
continue;
};
for next in next.iter() {
if graph[*next] != -1 {
continue;
}
graph[*next] = graph[cur] + 1;
queue.push_back(*next);
}
}
graph
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, Vec<(usize, usize)>, Vec<isize>);
#[test]
fn test() {
let tests = [
TestCase(3, 2, vec![(1, 3), (2, 3)], vec![0, 2, 1]),
TestCase(6 , 6, vec![(1, 4), (2, 3), (3, 4), (5, 6), (1, 2), (2, 4)], vec![0, 1, 2, 1, -1, -1]),
];
for TestCase(n, m, ab, expected) in tests {
assert_eq!(run(n, m, ab), expected);
}
}
}
ABC325 C - Sensors
C - Sensors(Difficulty : 400)
連結成分を数える。
コード例を見る
// https://atcoder.jp/contests/abc325/tasks/abc325_c
use std::collections::VecDeque;
fn check(r: isize, c: isize, h: isize, w: isize) -> bool {
r < 0 || c < 0 || r >= h || c >= w
}
fn run(h: usize, w: usize, s: Vec<&str>) -> usize {
let mut vec: Vec<Vec<char>> = s.into_iter().map(|s| s.chars().collect()).collect();
let mut ans = 0;
let dx = vec![0, 0, -1, 1, -1, -1, 1, 1];
let dy = vec![-1, 1, 0, 0, -1, 1, -1, 1];
for i in 0..h {
for j in 0..w {
if vec[i][j] == '.' {
continue;
}
ans += 1;
let mut queue = VecDeque::new();
queue.push_back((i, j));
while let Some((cur_i, cur_j)) = queue.pop_front() {
for i in 0..8 {
if check(cur_i as isize + dx[i], cur_j as isize + dy[i], h as isize, w as isize) {
continue;
}
let new_i = (cur_i as isize + dx[i]) as usize;
let new_j = (cur_j as isize + dy[i]) as usize;
if vec[new_i][new_j] == '#' {
vec[new_i][new_j] = '.';
queue.push_front((new_i, new_j));
}
}
}
}
}
ans
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, Vec<&'static str>, usize);
#[test]
fn test() {
let tests = [
TestCase(5, 6, vec![".##...", "...#..", "....##", "#.#...", "..#..."], 3),
TestCase(3, 3, vec!["#.#", ".#.", "#.#"], 1),
TestCase(4 , 2, vec!["..", "..", "..", ".."], 0),
TestCase(5, 47, vec![".#..#..#####..#...#..#####..#...#...###...#####", ".#.#...#.......#.#...#......##..#..#...#..#....", ".##....#####....#....#####..#.#.#..#......#####", ".#.#...#........#....#......#..##..#...#..#....", ".#..#..#####....#....#####..#...#...###...#####"], 7),
];
for TestCase(h, w, s, expected) in tests {
assert_eq!(run(h, w, s), expected);
}
}
}
ABC293 C - Make Takahashi Happy
C - Make Takahashi Happy(Difficulty : 431)
コード例を見る
// https://atcoder.jp/contests/abc293/tasks/abc293_c
use std::collections::VecDeque;
fn run(h: usize, w: usize, a: Vec<Vec<usize>>) -> usize {
let mut queue = VecDeque::new();
queue.push_back((0, 0, vec![a[0][0]]));
let dx = [0, 1];
let dy = [1, 0];
let mut ans = 0;
while let Some((cur_i, cur_j, visited)) = queue.pop_front() {
for i in 0..2 {
let new_i = cur_i + dx[i];
let new_j = cur_j + dy[i];
if new_i == h || new_j == w {
continue;
}
if visited.contains(&a[new_i][new_j]) {
continue;
}
if new_i == h-1 && new_j == w-1 {
ans += 1;
continue;
}
let mut new_visited = visited.clone();
new_visited.push(a[new_i][new_j]);
queue.push_back((new_i, new_j, new_visited));
}
}
ans
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, Vec<Vec<usize>>, usize);
#[test]
fn test() {
let tests = [
TestCase(3, 3, vec![vec![3, 2, 2], vec![2, 1, 3], vec![1, 5, 4]], 3),
TestCase(10, 10, vec![vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10], vec![11, 12, 13, 14, 15, 16, 17, 18, 19, 20], vec![21, 22, 23, 24, 25, 26, 27, 28, 29, 30], vec![31, 32, 33, 34, 35, 36, 37, 38, 39, 40], vec![41, 42, 43, 44, 45, 46, 47, 48, 49, 50], vec![51, 52, 53, 54, 55, 56, 57, 58, 59, 60], vec![61, 62, 63, 64, 65, 66, 67, 68, 69, 70], vec![71, 72, 73, 74, 75, 76, 77, 78, 79, 80], vec![81, 82, 83, 84, 85, 86, 87, 88, 89, 90], vec![91, 92, 93, 94, 95, 96, 97, 98, 99, 100]], 48620),
];
for TestCase(h, w, a, expected) in tests {
assert_eq!(run(h, w, a), expected);
}
}
}
ABC269 D - Do use hexagon grid
D - Do use hexagon grid(Difficulty : 629)
これも連結成分を数える問題です。
コード例を見る
// https://atcoder.jp/contests/abc269/tasks/abc269_d
use std::collections::VecDeque;
fn check(r: isize, c: isize) -> bool {
r < 0 || c < 0 || r >= 2001 || c >= 2001
}
fn run(_n: usize, xy: Vec<(isize, isize)>) -> usize {
let offset = 1000;
let xy: Vec<(isize, isize)> = xy.into_iter().map(|(x, y)| (x+offset, y+offset)).collect();
let mut vec = vec![vec![false; 2001]; 2001];
for (x, y) in xy.iter() {
vec[*x as usize][*y as usize] = true;
}
let dx = [0, 1, 1, 0, -1, -1];
let dy = [1, 1, 0, -1, -1, 0];
let mut ans = 0;
for (x, y) in xy.iter() {
if !vec[*x as usize][*y as usize] {
continue;
}
ans += 1;
let mut queue = VecDeque::new();
queue.push_back((*x, *y));
while let Some((cur_i, cur_j)) = queue.pop_front() {
if !vec[cur_i as usize][cur_j as usize] {
continue;
}
vec[cur_i as usize][cur_j as usize] = false;
for i in 0..6 {
if check(cur_i as isize + dx[i], cur_j as isize + dy[i]) {
continue;
}
let new_i = (cur_i as isize + dx[i]) as usize;
let new_j = (cur_j as isize + dy[i]) as usize;
if vec[new_i][new_j] {
queue.push_back((new_i as isize, new_j as isize));
}
}
}
}
ans
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, Vec<(isize, isize)>, usize);
#[test]
fn test() {
let tests = [
TestCase(6, vec![(-1, -1), (0, 1), (0, 2), (1, 0), (1, 2), (2, 0)], 3),
TestCase(4, vec![(5, 0), (4, 1), (-3, 4), (-2, -5)], 4),
TestCase(5, vec![(2, 1), (2, -1), (1, 0), (3, 1), (1, -1)], 1),
];
for TestCase(n, xy, expected) in tests {
assert_eq!(run(n, xy), expected);
}
}
}
ABC376 D - Cycle
D - Cycle(Difficulty : 743)
コード例を見る
// https://atcoder.jp/contests/abc376/tasks/abc376_d
use std::collections::{HashMap, VecDeque};
fn run(_n: usize, _m: usize, ab: Vec<(usize, usize)>) -> isize {
let mut hash_map = HashMap::new();
for (a, b) in ab {
hash_map.entry(a).or_insert_with(|| Vec::new()).push(b);
}
let mut queue = VecDeque::new();
queue.push_back((1, 0));
while let Some((cur, count)) = queue.pop_front() {
let Some(next) = hash_map.get(&cur) else {
continue;
};
for next in next.iter() {
if *next == 1 {
return count + 1;
}
queue.push_back((*next, count+1));
}
}
-1
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, Vec<(usize, usize)>, isize);
#[test]
fn test() {
let tests = [
TestCase(3, 3, vec![(1, 2), (2, 3), (3, 1)], 3),
TestCase(3, 2, vec![(1, 2), (2, 3)], -1),
TestCase(6, 9, vec![(6, 1), (1, 5), (2, 6), (2, 1), (3, 6), (4, 2), (6, 4), (3, 5), (5, 4)], 4),
];
for TestCase(n, m, ab, expected) in tests {
assert_eq!(run(n, m, ab), expected);
}
}
}
ABC383 C - Humidifier 3
C - Humidifier 3(Difficulty : 750)
多始点BFS
コード例を見る
// https://atcoder.jp/contests/abc383/tasks/abc383_c
use std::collections::VecDeque;
fn check(i: isize, j: isize, h: isize, w: isize) -> bool {
i < 0 || j < 0 || i == h || j == w
}
fn run(h: usize, w: usize, d: usize, s: Vec<&str>) -> usize {
let vec: Vec<Vec<char>> = s.into_iter().map(|s| s.chars().collect()).collect();
let mut graph = vec![vec![-1; w]; h];
let mut queue = VecDeque::new();
for i in 0..h {
for j in 0..w {
if vec[i][j] == 'H' {
queue.push_back((i, j));
graph[i][j] = 0;
}
}
}
let dx = [0, 1, 0, -1];
let dy = [1, 0, -1, 0];
while let Some((cur_i, cur_j)) = queue.pop_front() {
if d == 0 {
continue;
}
for i in 0..4 {
let new_i = cur_i as isize + dx[i];
let new_j = cur_j as isize + dy[i];
if check(new_i, new_j, h as isize, w as isize) {
continue;
}
let new_i = new_i as usize;
let new_j = new_j as usize;
if vec[new_i][new_j] == '#' || graph[new_i][new_j] != -1 {
continue;
}
graph[new_i][new_j] = graph[cur_i][cur_j] + 1;
queue.push_back((new_i, new_j));
}
}
graph.into_iter()
.map(|g| {
g.into_iter()
.filter(|i| {
*i >= 0 && *i <= d as isize
})
.count()
})
.sum()
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, usize, Vec<&'static str>, usize);
#[test]
fn test() {
let tests = [
TestCase(3, 4, 1, vec!["H...", "#..H", ".#.#"], 5),
TestCase(5, 6, 2, vec!["##...H", "H.....", "..H.#.", ".HH...", ".###.."], 21),
];
for TestCase(h, w, d, s, expected) in tests {
assert_eq!(run(h, w, d, s), expected);
}
}
}
ABC211 D - Number of Shortest paths
D - Number of Shortest paths(Difficulty : 755)
最短路をカウントする問題です。
コード例を見る
// https://atcoder.jp/contests/abc211/tasks/abc211_d
use std::collections::{HashMap, VecDeque};
fn run(n: usize, _m: usize, ab: Option<Vec<(usize, usize)>>) -> usize {
let Some(ab) = ab else {
return 0;
};
let mut vec = HashMap::new();
let md = 1000_000_007;
for (a, b) in ab {
vec.entry(a).or_insert_with(Vec::new).push(b);
vec.entry(b).or_insert_with(Vec::new).push(a);
}
let mut graph = vec![-1; n];
let mut queue = VecDeque::new();
let mut count = vec![0; n];
graph[0] = 0;
count[0] = 1;
queue.push_back(1);
while let Some(current) = queue.pop_front() {
if let Some(next) = vec.get(¤t) {
for &next in next.iter() {
if graph[next-1] == -1 {
queue.push_front(next);
graph[next-1] = graph[current-1] + 1;
count[next-1] = count[current-1];
} else if graph[next-1] == graph[current-1] + 1 {
count[next-1] += count[current-1];
count[next-1] %= md;
}
}
};
}
count[n-1] as usize
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, Option<Vec<(usize, usize)>>, usize);
#[test]
fn test() {
let tests = [
TestCase(4, 5, Some(vec![(2, 4), (1, 2), (2, 3), (1, 3), (3, 4)]), 2),
TestCase(4, 3, Some(vec![(1, 3), (2, 3), (2, 4)]), 1),
TestCase(2, 0, None, 0),
TestCase(7, 8, Some(vec![(1, 3), (1, 4), (2, 3), (2, 4), (2, 5), (2, 6), (5, 7), (6, 7)]), 4),
];
for TestCase(n, m, ab, expected) in tests {
assert_eq!(run(n, m, ab), expected);
}
}
}
ABC373 D - Hidden Weights
D - Hidden Weights(Difficulty : 765)
コード例を見る
// https://atcoder.jp/contests/abc373/tasks/abc373_d
use std::collections::{HashMap, VecDeque};
fn run(n: usize, _m: usize, uvw: Vec<(usize, usize, isize)>) -> Vec<isize> {
let mut hash_map = HashMap::new();
for (u, v, w) in uvw {
hash_map.entry(u).or_insert_with(|| Vec::new()).push((v, w));
hash_map.entry(v).or_insert_with(|| Vec::new()).push((u, -w));
}
let mut visited = vec![false; n+1];
let mut graph = vec![0; n+1];
for i in 1..=n {
if visited[i] {
continue;
}
let mut queue = VecDeque::new();
queue.push_back(i);
while let Some(cur) = queue.pop_front() {
if visited[cur] {
continue;
}
visited[cur] = true;
if let Some(next) = hash_map.get(&cur) {
for &(next_v, w) in next {
if visited[next_v] {
continue;
}
graph[next_v] = graph[cur] + w;
queue.push_back(next_v);
}
}
}
}
graph.into_iter().skip(1).collect()
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, Vec<(usize, usize, isize)>, Vec<isize>);
#[test]
fn test() {
let tests = [
TestCase(3, 3, vec![(1, 2, 2), (3, 2, 3), (1, 3, -1)], vec![0, 2, -1]),
TestCase(4, 2, vec![(2, 1, 5), (3, 4, -3)], vec![0, -5, 0, -3]),
TestCase(5, 7, vec![(2, 1, 18169343), (3, 1, 307110901), (4, 1, 130955934), (2, 3, -288941558), (2, 5, 96267410), (5, 3, -385208968), (4, 3, -176154967)], vec![0, -18169343, -307110901, -130955934, 78098067]),
];
for TestCase(n, m, uvw, expected) in tests {
assert_eq!(run(n, m, uvw), expected);
}
}
}
ABC168 D - .. (Double Dots)
D - .. (Double Dots)(Difficulty : 804)
コード例を見る
// https://atcoder.jp/contests/abc168/tasks/abc168_d
use std::collections::{HashMap, VecDeque};
fn run(n: usize, _m: usize, ab: Vec<(usize, usize)>) -> Vec<usize> {
let mut hash_map = HashMap::new();
for (a, b) in ab {
hash_map.entry(a-1).or_insert_with(Vec::new).push(b-1);
hash_map.entry(b-1).or_insert_with(Vec::new).push(a-1);
}
let mut ans = vec![0; n-1];
let mut graph = vec![false; n];
graph[0] = true;
let mut queue: VecDeque<usize> = VecDeque::new();
queue.push_back(0);
while let Some(cur) = queue.pop_front() {
let next = hash_map.get(&cur).unwrap();
for new_i in next.iter() {
if graph[*new_i] == true {
continue;
}
graph[*new_i] = true;
ans[*new_i-1] = cur + 1;
queue.push_back(*new_i);
}
}
ans
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, Vec<(usize, usize)>, Vec<usize>);
#[test]
fn test() {
let tests = [
TestCase(4, 4, vec![(1, 2), (2, 3), (3, 4), (4, 2)], vec![1, 2, 2]),
TestCase(6, 9, vec![(3, 4), (6, 1), (2, 4), (5, 3), (4, 6), (1, 5), (6, 2), (4, 5), (5, 6)], vec![6, 5, 6, 1, 1]),
];
for TestCase(n, m, ab, expected) in tests {
assert_eq!(run(n, m, ab), expected);
}
}
}
ABC387 D - Snaky Walk
D - Snaky Walk(Difficulty : 817)
縦移動と横移動を1回ずつ交互に行うところが難しいです。
コード例を見る
// https://atcoder.jp/contests/abc387/tasks/abc387_d
use std::collections::VecDeque;
fn check(r: isize, c: isize, h: isize, w: isize) -> bool {
r < 0 || c < 0 || r >= h || c >= w
}
fn run(h: usize, w: usize, s: Vec<&str>) -> isize {
let vec: Vec<Vec<char>> = s.into_iter().map(|s| s.chars().collect()).collect();
let mut pos_s = (0, 0);
let mut pos_g = (0, 0);
for h in 0..h {
for w in 0..w {
if vec[h][w] == 'S' {
pos_s = (h, w);
}
if vec[h][w] == 'G' {
pos_g = (h, w);
}
}
}
let d = [1, -1];
(0..2)
.filter_map(|i| {
let mut graph = vec![vec![-1; w]; h];
graph[pos_s.0][pos_s.1] = 0;
let mut queue = VecDeque::new();
queue.push_back(pos_s);
while let Some((cur_i, cur_j)) = queue.pop_front() {
for j in 0..2 {
let (new_i, new_j) = if (i + cur_i + cur_j) % 2 == 0 {
(cur_i as isize + d[j], cur_j as isize)
} else {
(cur_i as isize, cur_j as isize + d[j])
};
if check(new_i, new_j, h as isize, w as isize) {
continue;
}
let new_i = new_i as usize;
let new_j = new_j as usize;
if vec[new_i][new_j] == '#' || graph[new_i][new_j] != -1 {
continue;
}
graph[new_i][new_j] = graph[cur_i][cur_j] + 1;
queue.push_back((new_i, new_j));
}
}
(graph[pos_g.0][pos_g.1] != -1).then_some(graph[pos_g.0][pos_g.1])
})
.min()
.unwrap_or(-1)
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, Vec<&'static str>, isize);
#[test]
fn test() {
let tests = [
TestCase(3, 5, vec![".S#.G", ".....", ".#..."], 7),
TestCase(3, 5, vec!["..#.G", ".....", "S#..."], -1),
TestCase(8, 63, vec!["...............................................................","..S...#............................#####..#####..#####..####G..","..#...#................................#..#...#......#..#......","..#####..####...####..####..#..#...#####..#...#..#####..#####..","..#...#..#..#...#..#..#..#..#..#...#......#...#..#..........#..","..#...#..#####..####..####..####...#####..#####..#####..#####..", "................#.....#........#...............................", "................#.....#........#..............................."], 148),
];
for TestCase(h, w, s, expected) in tests {
assert_eq!(run(h, w, s), expected);
}
}
}
ABC016 C - 友達の友達
C - 友達の友達 (🧪 Difficulty : 830)
コード例を見る
// https://atcoder.jp/contests/abc016/tasks/abc016_3
use std::collections::{HashMap, VecDeque};
fn run(n: usize, _m: usize, ab: Vec<(usize, usize)>) -> Vec<usize> {
let mut hash_map = HashMap::new();
for (a, b) in ab {
hash_map.entry(a).or_insert_with(Vec::new).push(b);
hash_map.entry(b).or_insert_with(Vec::new).push(a);
}
let mut ans = Vec::new();
for i in 1..=n {
let mut graph = vec![false; n+1];
let mut queue = VecDeque::new();
// 友達の友達
let mut count = 0;
graph[i] = true;
queue.push_back((i, 2));
while let Some((x, k)) = queue.pop_front() {
if k == 0 {
continue;
}
if let Some(next) = hash_map.get(&x) {
for &n in next {
if !graph[n] {
graph[n] = true;
if k == 1 {
count += 1;
}
queue.push_back((n, k-1));
}
}
};
}
ans.push(count);
}
ans
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, Vec<(usize, usize)>, Vec<usize>);
#[test]
fn test() {
let tests = [
TestCase(3, 2, vec![(1, 2), (2, 3)], vec![1, 0, 1]),
TestCase(3, 3, vec![(1, 2), (1, 3), (2, 3)], vec![0, 0, 0]),
TestCase(8, 12, vec![(1, 6),(1, 7),(1, 8),(2, 5),(2, 6),(3, 5),(3, 6),(4, 5),(4, 8),(5, 6),(5, 7),(7, 8)], vec![4, 4, 4, 5, 2, 3, 4, 2]),
];
for TestCase(n, m, ab, expected) in tests {
assert_eq!(run(n, m, ab), expected);
}
}
}
ABC015 C - 高橋くんのバグ探し
C - 高橋くんのバグ探し(🧪 Difficulty : 912)
コード例を見る
// https://atcoder.jp/contests/abc015/tasks/abc015_3
use std::collections::VecDeque;
fn run(n: usize, _k: usize, t: Vec<Vec<usize>>) -> &'static str {
let mut queue = VecDeque::new();
for &n in &t[0] {
queue.push_back((0, vec![n]));
}
while let Some((i, vec, )) = queue.pop_front() {
if i + 1 == n {
if vec.iter().fold(0, |acc, &x| acc ^ x) == 0 {
return "Found";
}
continue;
}
let next_values = t[i + 1].clone();
for next in next_values {
let mut new_vec = vec.clone();
new_vec.push(next);
queue.push_back((i + 1, new_vec));
}
}
"Nothing"
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, Vec<Vec<usize>>, &'static str);
#[test]
fn test() {
let tests = [
TestCase(3, 4, vec![vec![1, 3, 5, 17], vec![2, 4, 2, 3], vec![1, 3, 2, 9]], "Found"),
TestCase(5, 3, vec![vec![89, 62, 15], vec![44, 36, 17], vec![4, 24, 24], vec![25, 98, 99], vec![66, 33, 57]], "Nothing"),
];
for TestCase(n, k, t, expected) in tests {
assert_eq!(run(n, k, t), expected);
}
}
}
ABC151 D - Maze Master
D - Maze Master(Difficulty : 959)
コード例を見る
// https://atcoder.jp/contests/abc151/tasks/abc151_d
use std::collections::VecDeque;
fn check(i: isize, j: isize, h: isize, w: isize) -> bool {
i < 0 || j < 0 || i >= h || j >= w
}
fn run(h: usize, w: usize, s: Vec<&str>) -> usize {
let vec: Vec<Vec<char>> = s.into_iter().map(|s| s.chars().collect()).collect();
let mut ans = 0;
let dx = [0, -1, 0, 1];
let dy = [-1, 0, 1, 0];
// '.'である全ての座標をスタートに設定し、最も大きい距離とansを比べる
for i in 0..h {
for j in 0..w {
if vec[i][j] == '#' {
continue;
}
let mut graph = vec![vec![-1; w]; h];
graph[i][j] = 0;
let mut queue = VecDeque::new();
queue.push_back((i, j));
while let Some((cur_i, cur_j)) = queue.pop_front() {
for k in 0..4 {
if check(cur_i as isize + dx[k], cur_j as isize + dy[k], h as isize, w as isize) {
continue;
}
let new_i = (cur_i as isize + dx[k]) as usize;
let new_j = (cur_j as isize + dy[k]) as usize;
if vec[new_i][new_j] == '#' || graph[new_i][new_j] != -1 {
continue;
}
graph[new_i][new_j] = graph[cur_i][cur_j] + 1;
ans = ans.max(graph[new_i][new_j] as usize);
queue.push_back((new_i, new_j));
}
}
}
}
ans
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, Vec<&'static str>, usize);
#[test]
fn test() {
let tests = [
TestCase(3, 3, vec!["...", "...", "..."], 4),
TestCase(3, 5, vec!["...#.", ".#.#.", ".#..."], 10),
];
for TestCase(h, w, s, expected) in tests {
assert_eq!(run(h, w, s), expected);
}
}
}
ABC088 D - Grid Repainting
D - Grid Repainting(Difficulty : 999)
コード例を見る
// https://atcoder.jp/contests/abc088/tasks/abc088_d
use std::collections::VecDeque;
// 境界チェック
fn check(r: isize, c: isize, h: usize, w: usize) -> bool {
r < 0 || c < 0 || r >= h as isize || c >= w as isize
}
fn run(h: usize, w: usize, s: Vec<&str>) -> isize {
let vec: Vec<Vec<char>> = s.iter().map(|str| str.chars().collect()).collect();
let mut graph: Vec<Vec<isize>> = vec![vec![-1; w]; h];
let mut queue: VecDeque<(usize, usize)> = VecDeque::new();
graph[0][0] = 0;
queue.push_back((0, 0));
let dx = [0, -1, 0, 1];
let dy = [-1, 0, 1, 0];
while let Some((cur_i, cur_j)) = queue.pop_front() {
for i in 0..4 {
let new_i = cur_i as isize + dx[i];
let new_j = cur_j as isize + dy[i];
if check(new_i, new_j, h, w) {
continue;
}
let (new_i, new_j) = (new_i as usize, new_j as usize);
if vec[new_i][new_j] == '#' || graph[new_i][new_j] != -1 {
continue;
}
graph[new_i][new_j] = graph[cur_i][cur_j] + 1;
queue.push_back((new_i, new_j));
}
}
// 右下にたどり着けない場合
if graph[h-1][w-1] == -1 {
return -1;
}
// #の数
let count: usize = s.into_iter().map(|str| str.chars().filter(|c| *c == '#').count()).sum();
// 全体のマス数 - 既存の#の数 - 最短経路のマス数
(h * w - count - 1) as isize - graph[h-1][w-1]
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, Vec<&'static str>, isize);
#[test]
fn test() {
let tests = [
TestCase(3, 3, vec!["..#", "#..", "..."], 2),
TestCase(10, 37, vec![".....................................", "...#...####...####..###...###...###..", "..#.#..#...#.##....#...#.#...#.#...#.", "..#.#..#...#.#.....#...#.#...#.#...#.", ".#...#.#..##.#.....#...#.#.###.#.###.", ".#####.####..#.....#...#..##....##...", ".#...#.#...#.#.....#...#.#...#.#...#.", ".#...#.#...#.##....#...#.#...#.#...#.", ".#...#.####...####..###...###...###..", "....................................."], 209),
];
for TestCase(h, w, s, expected) in tests {
assert_eq!(run(h, w, s), expected);
}
}
}
ABC276 E - Round Trip
E - Round Trip(Difficulty : 1058)
コード例を見る
// https://atcoder.jp/contests/abc276/tasks/abc276_e
use std::collections::VecDeque;
fn check(i: isize, j: isize, h: isize, w: isize) -> bool {
i < 0 || j < 0 || i >= h || j >= w
}
fn run(h: usize, w: usize, c: Vec<&str>) -> &'static str {
let vec: Vec<Vec<char>> = c.into_iter().map(|str| str.chars().collect()).collect();
let mut s_pos = (0, 0);
for i in 0..h {
for j in 0..w {
if vec[i][j] == 'S' {
s_pos = (i as isize, j as isize);
}
}
}
// スタートとゴールの組み合わせ
let pair = [
((-1, 0), (1, 0)), // 下上
((-1, 0), (0, 1)), // 下右
((-1, 0), (0, -1)), // 下左
((0, 1), (0, -1)), // 右左
((1, 0), (0, 1)), // 下右
((1, 0), (0, -1)), // 下左
];
let dx = [0, 1, 0, -1];
let dy = [1, 0, -1, 0];
for i in 0..6 {
let start_i = s_pos.0 + pair[i].0.0;
let start_j = s_pos.1 + pair[i].0.1;
let end_i = s_pos.0 + pair[i].1.0;
let end_j = s_pos.1 + pair[i].1.1;
if check(start_i, start_j, h as isize, w as isize) || check(end_i, end_j, h as isize, w as isize) {
continue;
}
if vec[start_i as usize][start_j as usize] == '#' || vec[end_i as usize][end_j as usize] == '#' {
continue;
}
let start = (start_i as usize, start_j as usize);
let mut dist = vec![vec![-1; w]; h];
dist[s_pos.0 as usize][s_pos.1 as usize] = 0;
dist[start.0][start.1] = 1;
let mut queue = VecDeque::new();
queue.push_front((start.0, start.1));
while let Some((cur_i, cur_j)) = queue.pop_front() {
for i in 0..4 {
if check(cur_i as isize + dx[i], cur_j as isize + dy[i], h as isize, w as isize) {
continue;
}
let next_i = (cur_i as isize + dx[i]) as usize;
let next_j = (cur_j as isize + dy[i]) as usize;
if vec[next_i][next_j] == '#' || dist[next_i][next_j] != -1 {
continue;
}
dist[next_i][next_j] = dist[cur_i][cur_j] + 1;
queue.push_back((next_i, next_j));
}
}
if dist[end_i as usize][end_j as usize] >= 3 {
return "Yes";
}
}
"No"
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, Vec<&'static str>, &'static str);
#[test]
fn test() {
let tests = [
TestCase(4, 4, vec!["....", "#.#.", ".S..", ".##."], "Yes"),
TestCase(2, 2, vec!["S.", ".#"], "No"),
TestCase(5, 7, vec![".#...#.", "..#.#..", "...S...", "..#.#..", ".#...#."], "No"),
TestCase(4, 4, vec!["...S", "....", "....", "...."], "Yes"),
];
for TestCase(h, w, c, expected) in tests {
assert_eq!(run(h, w, c), expected);
}
}
}
ARC031 B - 埋め立て
B - 埋め立て(Difficulty : 1106)
コード例を見る
// https://atcoder.jp/contests/arc031/tasks/arc031_2
use std::collections::VecDeque;
// 境界チェック
fn check(r: isize, c: isize, h: usize, w: usize) -> bool {
r < 0 || c < 0 || r == h as isize || c == w as isize
}
fn run(a: Vec<&str>) -> &'static str {
let vec: Vec<Vec<char>> = a.into_iter().map(|s| s.chars().collect()).collect();
for i in 0..10 {
for j in 0..10 {
let mut graph = vec![vec![-1; 10]; 10];
let mut queue = VecDeque::new();
queue.push_front((i, j));
graph[i][j] = 0;
let dx = [0, -1, 0, 1];
let dy = [-1, 0, 1, 0];
while let Some((cur_i, cur_j)) = queue.pop_front() {
for i in 0..4 {
let new_i = cur_i as isize + dx[i];
let new_j = cur_j as isize + dy[i];
if check(new_i, new_j, 10, 10) {
continue;
}
if vec[new_i as usize][new_j as usize] == 'x' || graph[new_i as usize][new_j as usize] != -1 {
continue;
}
graph[new_i as usize][new_j as usize] = graph[cur_i][cur_j] + 1;
queue.push_back((new_i as usize, new_j as usize));
}
}
let mut flag = true;
for i in 0..10 {
for j in 0..10 {
if vec[i][j] == 'o' && graph[i][j] == -1 {
flag = false;
}
}
}
if flag {
return "YES";
}
}
}
"NO"
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(Vec<&'static str>, &'static str);
#[test]
fn test() {
let tests = [
TestCase(vec!["xxxxxxxxxx", "xoooooooxx", "xxoooooxxx", "xxxoooxxxx", "xxxxoxxxxx", "xxxxxxxxxx", "xxxxoxxxxx", "xxxoooxxxx", "xxoooooxxx", "xxxxxxxxxx"], "YES"),
TestCase(vec!["xxxxxxxxxx", "xoooooooxx", "xxoooooxxx", "xxxoooxxxx", "xxxxxxxxxx", "xxxxxxxxxx", "xxxxxxxxxx", "xxxoooxxxx", "xxoooooxxx", "xxxxxxxxxx"], "NO"),
TestCase(vec!["xxxxoxxxxx", "xxxxoxxxxx", "xxxxoxxxxx", "xxxxoxxxxx", "ooooxooooo", "xxxxoxxxxx", "xxxxoxxxxx", "xxxxoxxxxx", "xxxxoxxxxx", "xxxxoxxxxx"], "YES"),
];
for TestCase(a, expected) in tests {
assert_eq!(run(a), expected);
}
}
}
AGC033 A - Darker and Darker
A - Darker and Darker(Difficulty : 1159)
コード例を見る
// https://atcoder.jp/contests/agc033/tasks/agc033_a
use std::collections::VecDeque;
// 境界チェック
fn check(r: isize, c: isize, h: usize, w: usize) -> bool {
r < 0 || c < 0 || r >= h as isize || c >= w as isize
}
fn run(h: usize, w: usize, a: Vec<&str>) -> usize {
let vec: Vec<Vec<char>> = a.into_iter().map(|s| s.chars().collect()).collect();
let mut graph = vec![vec![-1; w]; h];
let mut queue = VecDeque::new();
for i in 0..h {
for j in 0..w {
if vec[i][j] == '#' {
graph[i][j] = 0;
queue.push_back((i, j));
}
}
}
let dx = [0, -1, 0, 1];
let dy = [-1, 0, 1, 0];
while let Some((cur_r, cur_c)) = queue.pop_front() {
for i in 0..4 {
let new_r = cur_r as isize + dx[i];
let new_c = cur_c as isize + dy[i];
if check(new_r, new_c, h, w) {
continue;
}
let (new_r, new_c) = (new_r as usize, new_c as usize);
if vec[new_r][new_c] == '#' || graph[new_r][new_c] != -1 {
continue;
}
graph[new_r][new_c] = graph[cur_r][cur_c] + 1;
queue.push_back((new_r, new_c));
}
}
graph.iter()
.flat_map(|row| row.iter())
.copied()
.max()
.unwrap() as usize
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, Vec<&'static str>, usize);
#[test]
fn test() {
let tests = [
TestCase(3, 3, vec!["...", ".#.", "..."], 2),
TestCase(6, 6, vec!["..#..#", "......", "#..#..", "......", ".#....", "....#."], 3),
];
for TestCase(h, w, a, expected) in tests {
assert_eq!(run(h, w, a), expected);
}
}
}
ユークリッドの互除法
アルゴリズムと数学 演習問題集 015 - calculate gcd
コード例を見る
// https://atcoder.jp/contests/math-and-algorithm/tasks/math_and_algorithm_o
fn gcd(a: usize, b: usize) -> usize {
if b == 0 {
a
} else {
gcd(b, a % b)
}
}
fn run(a: usize, b: usize) -> usize {
gcd(a, b)
}
fn main() {
println!("{}", run(33, 88));
println!("{}", run(123, 777));
}
arc105 b - max-=min
b - max-=min(difficulty : 366)
コード例を見る
// https://atcoder.jp/contests/arc105/tasks/arc105_b
fn gcd(a: usize, b: usize) -> usize {
if b == 0 {
a
} else {
gcd(b, a % b)
}
}
fn run(n: usize, a: vec<usize>) -> usize {
let mut ans = a[0];
for b in 1..a.len() {
ans = ans.min(gcd(ans, a[b]));
}
ans
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(2, run(3, vec![2, 6, 6]));
assert_eq!(42, run(15, vec![546, 3192, 1932, 630, 2100, 4116, 3906, 3234, 1302, 1806, 3528, 3780, 252, 1008, 588]));
}
}
abc109 c - skip
c - skip(difficulty : 542)
コード例を見る
fn gcd(a: isize, b: isize) -> isize {
if b == 0 {
a
} else {
gcd(b, a % b)
}
}
fn run(_n: usize, x: isize, v: Vec<isize>) -> isize {
v.iter()
.skip(1)
.fold((x - &v[0]).abs(), |state, num| {
gcd(state, (x - num).abs())
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(2, run(3, 3, vec![1, 7, 11]));
assert_eq!(24, run(3, 81, vec![33, 105, 57]));
assert_eq!(999999999, run(1, 1, vec![1000000000]));;
}
}
ABC118 C - Monsters Battle Royale
C - Monsters Battle Royale(Difficulty : 646)
コード例を見る
// https://atcoder.jp/contests/abc118/tasks/abc118_c
fn gcd(a: usize, b: usize) -> usize {
if b == 0 {
a
} else {
gcd(b, a % b)
}
}
fn run(_n: usize, v: Vec<usize>) -> usize {
v.iter()
.fold(0, |state, num| {
gcd(state, *num)
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(2, run(4, vec![2, 10, 8, 40]));
assert_eq!(1, run(4, vec![5, 13, 8, 1000000000]));
assert_eq!(1000000000, run(3, vec![1000000000, 1000000000, 1000000000]));
}
}
ランレングス圧縮
ランレングス圧縮の魅力 ~茶diff攻略への強い味方~ - YU2TA7KA’s BLOG ~take one step at a time~
全要素を回していると間に合わないのでランレングス圧縮で要素数を減らし計算量を削減する、という問題が多いです。また、同じ文字で固めて、文字が切り替わるタイミングで何かする、という問題もあります。
なお、itertools
のdedup_with_count
を使えば簡単にランレングス圧縮できます。
use itertools::Itertools;
fn main() {
let vec = vec!['a', 'a', 'a', 'b', 'a', 'c', 'c'];
for (count, char) in vec.into_iter().dedup_with_count() {
println!("count={}, char={}", count, char);
// count=3, char=a
// count=1, char=b
// count=1, char=a
// count=2, char=c
}
}
ABC019 B - 高橋くんと文字列圧縮
B - 高橋くんと文字列圧縮(🧪 Difficulty : 534)
そのものズバリの問題です。
コード例を見る
fn run_length(s: Vec<char>) -> Vec<(char, usize)> {
let mut result = vec![];
let mut current = (s[0], 1);
for i in 1..s.len() {
if s[i] == current.0 {
current.1 += 1;
} else {
result.push(current);
current = (s[i], 1);
}
}
result.push(current);
result
}
fn run(s: &str) -> String {
let rle = run_length(s.chars().collect());
rle.iter()
.map(|(c, i)| {
format!("{}{}", c, i)
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(String::from("a2b3a2d1"), run("aabbbaad"));
assert_eq!(String::from("a2b12x1y1z1a1"), run("aabbbbbbbbbbbbxyza"));
assert_eq!(String::from("e1d1c1b1a1"), run("edcba"));
}
}
ABC143 C - Slimes
C - Slimes(Difficulty : 66)
連続している部分をひとまとまりとして扱います。
コード例を見る
fn run_lengths(s: Vec<char>) -> Vec<(char, usize)> {
let mut run_lengths = vec![];
let mut current = (s[0], 1);
for i in 1..s.len() {
if s[i] == current.0 {
current.1 += 1;
} else {
run_lengths.push(current);
current = (s[i], 1);
}
}
run_lengths.push(current);
run_lengths
}
fn run(_n: usize, s: &str) -> usize {
run_lengths(s.chars().collect()).len()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(5, run(10, "aabbbbaaca"));
assert_eq!(1, run(5, "aaaaa"));
assert_eq!(10, run(20, "xxzaffeeeeddfkkkkllq"));
}
#[test]
fn test2() {
assert_eq!(5, run2(10, "aabbbbaaca"));
assert_eq!(1, run2(5, "aaaaa"));
assert_eq!(10, run2(20, "xxzaffeeeeddfkkkkllq"));
}
}
ABC299 C - Dango
C - Dango(Difficulty : 191)
コード例を見る
// https://atcoder.jp/contests/abc299/tasks/abc299_c
use itertools::Itertools;
fn run(_n: usize, s: &str) -> isize {
let run_length: Vec<(usize, char)> = s.chars().dedup_with_count().collect();
run_length
.iter()
.enumerate()
.filter_map(|(i, (count, c))| {
if *c == 'o' {
let left = i > 0 && run_length[i-1].1 == '-';
let right = i+1 < run_length.len() && run_length[i+1].1 == '-';
if left || right {
return Some(count);
}
}
None
})
.max()
.map(|x| *x as isize)
.unwrap_or(-1)
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, &'static str, isize);
#[test]
fn test() {
let tests = [
TestCase(10, "o-oooo---o", 4),
TestCase(1, "-", -1),
TestCase(30, "-o-o-oooo-oo-o-ooooooo--oooo-o", 7),
];
for TestCase(n, s, expected) in tests {
assert_eq!(run(n, s), expected);
}
}
}
ABC329 C - Count xxx
C - Count xxx(Difficulty : 205)
コード例を見る
// https://atcoder.jp/contests/abc329/tasks/abc329_c
use std::collections::HashMap;
fn run(n: usize, s: &str) -> usize {
let chars: Vec<char> = s.chars().collect();
let mut hashmap = HashMap::new();
let mut count = 1;
hashmap.insert(chars[0], 1);
for i in 1..n {
if chars[i] == chars[i-1] {
count += 1;
if count > *hashmap.get(&chars[i]).unwrap() {
*hashmap.get_mut(&chars[i]).unwrap() += 1;
}
} else {
count = 1;
hashmap.entry(chars[i]).or_insert(1);
}
}
hashmap.values().sum()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(4, run(6, "aaabaa"));
assert_eq!(1, run(1, "x"));
assert_eq!(8, run(12, "ssskkyskkkky"));
}
}
ABC380 C - Move Segment
C - Move Segment(Difficulty : 223)
コード例を見る
// https://atcoder.jp/contests/abc380/tasks/abc380_c
fn run_length(s: Vec<char>) -> Vec<(char, usize)> {
let mut result = vec![];
let mut current = (s[0], 1);
for i in 1..s.len() {
if s[i] == current.0 {
current.1 += 1;
} else {
result.push(current);
current = (s[i], 1);
}
}
result.push(current);
result
}
fn run(_n: usize, k: usize, s: &str) -> String {
let mut rle = run_length(s.chars().collect());
let one_idx = rle
.iter()
.enumerate()
.filter(|&(_, &(ch, _))| ch == '1')
.nth(k - 1)
.map(|(i, _)| i)
.unwrap();
if one_idx > 0 && rle[one_idx - 1].0 == '0' {
rle.swap(one_idx - 1, one_idx);
}
rle
.iter()
.flat_map(|&(ch, len)| std::iter::repeat(ch).take(len))
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, &'static str, &'static str);
#[test]
fn test() {
let tests = [
TestCase(15, 3, "010011100011001", "010011111000001"),
TestCase(10, 2, "1011111111", "1111111110"),
];
for TestCase(n, k, s, expected) in tests {
assert_eq!(run(n, k, s), expected);
}
}
}
ABC259 C - XX to XXX
C - XX to XXX(Difficulty : 451)
コード例を見る
// https://atcoder.jp/contests/abc259/tasks/abc259_c
use std::iter::zip;
fn run_lengths(s: Vec<char>) -> Vec<(char, usize)> {
let mut i = 0;
let mut run_lengths = vec![];
let mut current = (s[0], 0);
loop {
while i < s.len() && s[i] == current.0 {
current.1 += 1;
i += 1;
}
run_lengths.push(current);
if i == s.len() {
break;
} else {
current = (s[i], 0);
}
}
run_lengths
}
fn run(s: &str, t: &str) -> &'static str {
let s_length = run_lengths(s.chars().collect());
let t_length = run_lengths(t.chars().collect());
if s_length.len() != t_length.len() {
return "No";
}
if s_length.into_iter()
.zip(t_length.into_iter())
.any(|(s, t)| {
// 文字が違う場合
// tが長さ2以上なのにsが長さ1しかない場合
// sの方が長い場合(tを増やすことはできないので)
s.0 != t.0 || (t.1 > 1 && s.1 == 1) || s.1 > t.1
}) {
"No"
} else {
"Yes"
}
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(&'static str, &'static str, &'static str);
#[test]
fn test() {
let tests = [
TestCase("abbaac", "abbbbaaac", "Yes"),
TestCase("xyzz", "xyyzz", "No"),
TestCase("aa", "aa", "Yes"),
TestCase("aa", "aabb", "No"),
];
for TestCase(s, t, expected) in tests {
assert_eq!(run(s, t), expected);
}
}
}
ABC247 D - Cylinder
D - Cylinder(Difficulty : 468)
AGC039 A - Connection and Disconnection
A - Connection and Disconnection(Difficulty : 517)
コード例を見る
// https://atcoder.jp/contests/agc039/tasks/agc039_a
use itertools::Itertools;
fn run_length(s: &str) -> Vec<(char, usize)> {
let mut i = 0;
let mut run_lengths = vec![];
let mut current = (s.chars().nth(0).unwrap(), 0);
loop {
while i < s.len() && s.chars().nth(i).unwrap() == current.0 {
current.1 += 1;
i += 1;
}
run_lengths.push(current);
if i == s.len() {
return run_lengths;
} else {
current = (s.chars().nth(i).unwrap(), 0);
}
}
}
fn run(s: &str, k: usize) -> usize {
// 全て同じ文字だった場合
if s.chars().all_equal() {
return s.len() * k / 2
}
let rle = run_length(s);
// 最初と最後の文字が違うなら、連続している数 / 2を合計してk倍して返す
if s.chars().nth(0) != s.chars().last() {
rle.iter()
.map(|(_, num)| num / 2 )
.sum::<usize>() * k
} else {
let mut ans = 0;
// 両端以外を合計する
for i in 1..rle.len()-1 {
ans += rle[i].1 / 2;
}
let left = rle[0].1;
let right = rle.iter().last().unwrap().1;
ans * k + (left + right) / 2 * (k - 1) + left/2 + right/2
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(4, run("issii", 2));
assert_eq!(81, run("qq", 81));
assert_eq!(8999939997, run("cooooooooonteeeeeeeeeest", 999993333));
assert_eq!(50000000000, run("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 1000000000));
assert_eq!(49499999950, run("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 999999999));
}
}
ABC047 C - 一次元リバーシ
C - 一次元リバーシ (Difficulty : 755)
文字が切り替わる回数を数えます。
コード例を見る
// https://atcoder.jp/contests/abc047/tasks/arc063_a
fn run_lengths(s: Vec<char>) -> Vec<(char, usize)> {
let mut run_lengths = vec![];
let mut current = (s[0], 1);
for i in 1..s.len() {
if s[i] == current.0 {
current.1 += 1;
} else {
run_lengths.push(current);
current = (s[i], 1);
}
}
run_lengths.push(current);
run_lengths
}
fn run(s: &str) -> usize {
run_lengths(s.chars().collect()).len() - 1
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(1, run("BBBWW"));
assert_eq!(0, run("WWWWWW"));
assert_eq!(9, run("WBWBWBWBWB"));
}
}
ABC127 D - Integer Cards
D - Integer Cards(Difficulty : 887)
AGC016 A - Shrinking
A - Shrinking(Difficulty : 951)
これはランレングス圧縮とは言えないですが、連続する文字数を数えるという意味では考え方は似てると思います。
コード例を見る
// https://atcoder.jp/contests/agc016/tasks/agc016_a
use itertools::Itertools;
// c以外の文字が最大何文字続くかをカウント
fn max_streak(c: char, s: &str) -> usize {
s.chars()
.scan(0, |streak, char| {
if char == c {
*streak = 0;
Some(0)
} else {
*streak += 1;
Some(*streak)
}
})
.max()
.unwrap()
}
fn run(s: &str) -> usize {
if s.chars().all_equal() {
return 0;
}
('a'..='z')
.map(|c| {
max_streak(c, s)
})
.min()
.unwrap()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(3, run("serval"));
assert_eq!(2, run("jackal"));
assert_eq!(0, run("zzz"));
assert_eq!(8, run("whbrjpjyhsrywlqjxdbrbaomnw"));
assert_eq!(50, run("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"));
assert_eq!(0, run("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"));
assert_eq!(4, run("dcddccddccdcddddddccdccdcddccdccccdddddddddccddccccdddddcdcdcccdcccddddddcdddddccdcccddcc"));
}
}
ABC061 C - Big Array
C - Big Array(Difficulty : 887)
これまでは「入力をランレングス圧縮して扱う」問題でしたが、この問題はランレングス圧縮された状態で入力が与えられると言えます。圧縮されたものを解凍するイメージです。
コード例を見る
// https://atcoder.jp/contests/abc061/tasks/abc061_c
fn run(_n: usize, k: usize, ab: Vec<(usize, usize)>) -> usize {
let mut vec = ab.clone();
vec.sort_by(|a, b| a.0.cmp(&b.0));
let mut rest = k;
for i in vec {
if rest <= i.1 {
return i.0
} else {
rest -= i.1
}
}
unreachable!();
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(3, run(3, 4, vec![(1, 1), (2, 2), (3, 3)]));
assert_eq!(1, run(10, 500000, vec![(1, 100000), (1, 100000), (1, 100000), (1, 100000), (1, 100000), (100000, 100000), (100000, 100000), (100000, 100000), (100000, 100000), (100000, 100000)]));
}
}
動的計画法
ABC087 C - Candies
C - Candies(Difficulty : 312)
N
が100と小さいので全探索でもいけますがDPで。
コード例を見る
// https://atcoder.jp/contests/abc087/tasks/arc090_a
fn run(n: usize, a: [Vec<usize>; 2]) -> usize {
let mut dp: Vec<Vec<usize>> = vec![vec![], vec![]];
dp[0].push(a[0][0]);
for i in 1..n {
let prev = dp[0][i-1];
dp[0].push(prev + a[0][i]);
}
dp[1].push(a[0][0] + a[1][0]);
for i in 1..n {
let prev = dp[1][i-1];
let next = dp[0][i];
dp[1].push(prev.max(next) + a[1][i]);
}
dp[1][n-1]
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(14, run(5, [vec![3, 2, 2, 4, 1], vec![1, 2, 2, 2, 1]]));
assert_eq!(5, run(4, [vec![1, 1, 1, 1], vec![1, 1, 1, 1]]));
assert_eq!(29, run(7, [vec![3, 3, 4, 5, 4, 5, 3], vec![5, 3, 4, 4, 2, 3, 2]]));
assert_eq!(5, run(1, [vec![2], vec![3]]));
}
}
ABC245 C - Choose Elements
C - Choose Elements(Difficulty : 403)
コード例を見る
// https://atcoder.jp/contests/abc245/tasks/abc245_c
fn run(n: usize, k: isize, a: Vec<isize>, b: Vec<isize>) -> &'static str {
let mut dp_a = vec![false; n];
let mut dp_b = vec![false; n];
dp_a[0] = true;
dp_b[0] = true;
for i in 0..n-1 {
if dp_a[i] == true {
dp_a[i+1] |= (a[i] - a[i+1]).abs() <= k;
dp_b[i+1] |= (a[i] - b[i+1]).abs() <= k;
}
if dp_b[i] == true {
dp_a[i+1] |= (b[i] - a[i+1]).abs() <= k;
dp_b[i+1] |= (b[i] - b[i+1]).abs() <= k;
}
}
if dp_a[n-1] || dp_b[n-1] {
"Yes"
} else {
"No"
}
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, isize, Vec<isize>, Vec<isize>, &'static str);
#[test]
fn test() {
let tests = [
TestCase(5, 4, vec![9, 8, 3, 7, 2], vec![1, 6, 2, 9, 5], "Yes"),
TestCase(3, 2, vec![1, 3, 100, 101, 102], vec![1, 3, 100, 101, 102], "No"),
TestCase(4, 1000000000, vec![1, 1, 1000000000, 1000000000], vec![1, 1000000000, 1, 1000000000], "Yes"),
];
for TestCase(n, k, a, b, expected) in tests {
assert_eq!(run(n, k, a, b), expected);
}
}
}
貪欲法
ABC011 C - 123引き算
C - 123引き算(🧪 Difficulty : 810)
コード例を見る
// https://atcoder.jp/contests/abc011/tasks/abc011_3
fn run(n: isize, ng: [isize; 3]) -> &'static str {
if ng.contains(&n) {
return "NO";
}
let mut cur = n;
for _ in 0..100 {
// 3引いた数がNGじゃないなら3引く
// 2, 1も同様
for j in (1..=3).rev() {
if ng.contains(&(cur - j)) {
continue;
}
cur -= j;
break;
}
if cur <= 0 {
return "YES";
}
}
"NO"
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(isize, [isize; 3], &'static str);
#[test]
fn test() {
let tests = [
TestCase(2, [1, 7, 15], "YES"),
TestCase(5, [1, 4, 2], "YES"),
TestCase(300, [57, 121, 244], "NO"),
];
for TestCase(n, ng, expected) in tests {
assert_eq!(run(n, ng), expected);
}
}
}
尺取り法
ABC038 C - 単調増加
C - 単調増加(Difficulty : 894)
コード例を見る
// https://atcoder.jp/contests/abc038/tasks/abc038_c
fn run(n: usize, a: Vec<usize>) -> usize {
let mut ans = 0;
let mut r = 0;
for l in 0..n {
while r < n && (r <= l || a[r] > a[r-1]) {
r += 1;
}
ans += r - l;
if l == r {
r += 1;
}
}
ans
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, Vec<usize>, usize);
#[test]
fn test() {
let tests = [
TestCase(5, vec![1, 2, 3, 2, 1], 8),
TestCase(4, vec![1, 2, 3, 4], 10),
TestCase(6, vec![3, 3, 4, 1, 2, 2], 8),
TestCase(6, vec![1, 5, 2, 3, 4, 2], 10),
];
for TestCase(n, a, expected) in tests {
assert_eq!(run(n, a), expected);
}
}
}
データ構造
累積和
ABC099 B - Stone Monument
B - Stone Monument(Difficulty : 131)
コード例を見る
// https://atcoder.jp/contests/abc099/tasks/abc099_b
fn run(a: usize, b: usize) -> usize {
let mut cum_sum = Vec::new();
for i in 0..=(b-a) {
if i == 0 {
cum_sum.push(i)
} else {
cum_sum.push(cum_sum[i-1] + i);
}
}
*cum_sum.iter().last().unwrap() - b
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(2, run(8, 13));
assert_eq!(1, run(54, 65));
}
}
ABC371 D - 1D Country
D - 1D Country(Difficulty : 408)
コード例を見る
// https://atcoder.jp/contests/abc371/tasks/abc371_d
fn run(n: usize, x: Vec<isize>, p: Vec<isize>, q: usize, lr: Vec<(isize, isize)>) -> Vec<isize> {
let mut cum = vec![0];
for i in 1..=n {
cum.push(cum[i-1] + p[i-1])
}
(0..q)
.map(|i| {
let l = x.partition_point(|x| *x < lr[i].0);
let r = x.partition_point(|x| *x < lr[i].1 + 1);
cum[r] - cum[l]
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, Vec<isize>, Vec<isize>, usize, Vec<(isize, isize)>, Vec<isize>);
#[test]
fn test() {
let tests = [
TestCase(4, vec![1, 3, 5, 7], vec![1, 2, 3, 4], 4, vec![(1, 1), (2, 6), (0, 10), (2, 2)], vec![1, 5, 10, 0]),
TestCase(7, vec![-10, -5, -3, -1, 0, 1, 4], vec![2, 5, 6, 5, 2, 1, 7], 8, vec![(-7, 7), (-1, 5), (-10, -4), (-8, 10), (-5, 0), (-10, 5), (-8, 7), (-8, -3)], vec![26, 15, 7, 26, 18, 28, 26, 11]),
];
for TestCase(n, x, p, q, lr, expected) in tests {
assert_eq!(run(n, x, p, q, lr), expected);
}
}
}
ABC122 C - GeT AC
C - GeT AC (Difficulty : 700)
コード例を見る
// https://atcoder.jp/contests/abc122/tasks/abc122_c
fn run(n: usize, _q: usize, s: &str, lr: Vec<(usize, usize)>) -> Vec<usize> {
let mut ans = Vec::new();
let mut cum_sum = vec![0; n];
let chars = s.chars().collect::<Vec<char>>();
for (i, lr) in chars.windows(2).enumerate() {
if lr[0] == 'A' && lr[1] == 'C' {
cum_sum[i+1] = cum_sum[i]+1;
} else {
cum_sum[i+1] = cum_sum[i];
}
}
for (l, r) in lr.iter() {
ans.push(cum_sum[r-1] - cum_sum[l-1]);
}
ans
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, &'static str, Vec<(usize, usize)>, Vec<usize>);
#[test]
fn test() {
let tests = [
TestCase(8, 3, "ACACTACG", vec![(3, 7), (2, 3), (1, 8)], vec![2, 0, 3]),
];
for TestCase(n, q, s, lr, expected) in tests {
assert_eq!(run(n, q, s, lr), expected);
}
}
}
いもす法
ABC014 C - AtColor
C - AtColor(🧪 Difficulty : 1276)
コード例を見る
// https://atcoder.jp/contests/abc014/tasks/abc014_3
fn run(_n: usize, ab: Vec<(usize, usize)>) -> usize {
let mut vec: Vec<isize> = vec![0; 1_000_000+2];
for (a, b) in ab {
vec[a] += 1;
vec[b+1] -= 1;
}
let mut ans = vec![vec[0]];
for i in 1..vec.len() {
ans.push(ans[i-1] + vec[i]);
}
ans.into_iter()
.max()
.unwrap() as usize
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, Vec<(usize, usize)>, usize);
#[test]
fn test() {
let tests = [
TestCase(4, vec![(0, 2), (2, 3), (2, 4), (5, 6)], 3),
TestCase(4, vec![(1000000, 1000000), (1000000, 1000000), (0, 1000000), (1, 1000000)], 4),
];
for TestCase(n, ab, expected) in tests {
assert_eq!(run(n, ab), expected);
}
}
}
スタック-8問
ABC286 B - Cat
B - Cat(Difficulty : 32)
コード例を見る
// https://atcoder.jp/contests/abc286/tasks/abc286_b
fn run(n: usize, s: &str) -> String {
let chars: Vec<char> = s.chars().collect();
chars.iter()
.fold(Vec::new(), |mut stack, c| {
stack.push(*c);
if stack.len() >= 2 && stack[stack.len()-2..] == ['n', 'a'] {
stack.truncate(stack.len()-2);
stack.append(&mut vec!['n', 'y', 'a']);
}
stack
})
.iter()
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(String::from("nyaan"), run(4, "naan"));
assert_eq!(String::from("near"), run(4, "near"));
assert_eq!(String::from("nyationyal"), run(8, "national"));
}
}
ABC351 C - Merge the balls
C - Merge the balls(Difficulty : 228)
コード例を見る
// https://atcoder.jp/contests/abc351/tasks/abc351_c
fn run(_n: usize, a: Vec<usize>) -> usize {
a.into_iter()
.fold(Vec::new(), |mut stack, num| {
stack.push(num);
loop {
let len = stack.len();
if len > 1 && stack[len-2] == stack[len-1] {
let i = stack[len-1];
stack.truncate(len-2);
stack.push(i+1);
} else {
break stack;
}
}
})
.len()
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, Vec<usize>, usize);
#[test]
fn test() {
let tests = [
TestCase(7 , vec![2, 1, 1, 3, 5, 3, 3], 3),
TestCase(5, vec![0, 0, 0, 1, 2], 4),
];
for TestCase(n, a, expected) in tests {
assert_eq!(run(n, a), expected);
}
}
}
ABC394 D - Colorful Bracket Sequence
D - Colorful Bracket Sequence(Difficulty : 253)
コード例を見る
// https://atcoder.jp/contests/abc394/tasks/abc394_d
fn run(s: &str) -> &'static str {
let mut stack = Vec::new();
for c in s.chars() {
stack.push(c);
if stack.len() > 1 {
let len = stack.len();
if stack.ends_with(&['(', ')']) ||
stack.ends_with(&['[', ']']) ||
stack.ends_with(&['<', '>'])
{
stack.truncate(len-2);
}
}
}
if stack.is_empty() {
"Yes"
} else {
"No"
}
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(&'static str, &'static str);
#[test]
fn test() {
let tests = [
TestCase("([])<>()", "Yes"),
TestCase("([<)]>", "No"),
TestCase("())", "No"),
];
for TestCase(s, expected) in tests {
assert_eq!(run(s), expected);
}
}
}
ABC283 D - Scope
D - Scope(Difficulty : 453)
コード例を見る
fn run(s: &str) -> &'static str {
let s: Vec<char> = s.chars().collect();
let mut is_stacked = vec![false; 26];
let mut stack = Vec::new();
for c in s {
match c {
'(' => {
stack.push(c);
},
')' => {
while let Some(popped) = stack.pop() {
if popped == '(' {
break;
}
is_stacked[(popped as u8 - b'a') as usize] = false;
}
},
_ => {
if is_stacked[(c as u8 - b'a') as usize] {
return "No";
}
is_stacked[(c as u8 - b'a') as usize] = true;
stack.push(c);
}
}
}
"Yes"
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(&'static str, &'static str);
#[test]
fn test() {
let tests = [
TestCase("((a)ba)", "Yes"),
TestCase("(a(ba))", "No"),
TestCase("(((())))", "Yes"),
TestCase("abca", "No"),
];
for TestCase(s, expected) in tests {
assert_eq!(run(s), expected);
}
}
}
ABC328 D - Take ABC
D - Take ABC(Difficulty : 555)
コード例を見る
// https://atcoder.jp/contests/abc328/tasks/abc328_d
fn run(s: &str) -> String {
let chars: Vec<char> = s.chars().collect();
let mut ans: Vec<char> = Vec::new();
for c in chars {
ans.push(c);
let len = ans.len();
if len >= 3 && &ans[len-3..] == ['A', 'B', 'C'] {
ans.truncate(len-3);
}
}
ans.iter().collect()
}
/* foldを使った別解 */
fn run2(s: &str) -> String {
let chars: Vec<char> = s.chars().collect();
chars.iter()
.fold(Vec::new(), |mut state, c: &char| {
state.push(*c);
let len = state.len();
if len >= 3 && &state[state.len()-3..] == ['A', 'B', 'C'] {
state.truncate(state.len()-3);
}
state
})
.iter()
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(String::from("BCAC"), run("BAABCBCCABCAC"));
assert_eq!(String::new(), run("ABCABC"));
assert_eq!(String::from("AAABBBCCC"), run("AAABCABCABCAABCABCBBBAABCBCCCAAABCBCBCC"));
}
#[test]
fn test2() {
assert_eq!(String::from("BCAC"), run2("BAABCBCCABCAC"));
assert_eq!(String::new(), run2("ABCABC"));
assert_eq!(String::from("AAABBBCCC"), run2("AAABCABCABCAABCABCBBBAABCBCCCAAABCBCBCC"));
}
}
ARC108 B - Abbreviate Fox
B - Abbreviate Fox(Difficulty : 681)
コード例を見る
// https://atcoder.jp/contests/arc108/tasks/arc108_b
fn run(_n: usize, s: &str) -> usize {
let chars: Vec<char> = s.chars().collect();
chars.iter()
.fold(Vec::new(), |mut stack, c| {
stack.push(*c);
if stack.len() >= 3 && stack[stack.len()-3..] == ['f', 'o', 'x'] {
stack.truncate(stack.len()-3);
}
stack
})
.len()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(3, run(6, "icefox"));
assert_eq!(7, run(7, "firebox"));
assert_eq!(27, run(48, "ffoxoxuvgjyzmehmopfohrupffoxoxfofofoxffoxoxejffo"));
}
}
AGC005 A - STring
A - STring(Difficulty : 1054)
コード例を見る
// https://atcoder.jp/contests/agc005/tasks/agc005_a
fn run(s: &str) -> usize {
let chars: Vec<char> = s.chars().collect();
chars.iter()
.fold(Vec::new(), |mut stack, c| {
stack.push(*c);
let len = stack.len();
if len >= 2 && stack[len-2] == 'S' && stack[len-1] == 'T' {
stack.truncate(len-2);
stack
} else {
stack
}
})
.iter()
.count()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(4, run("TSTTSS"));
assert_eq!(0, run("SSTTST"));
assert_eq!(4, run("TSSTTTSS"));
}
}
HashMap
ABC230 B - Election
B - Election(Difficulty : 39)
まさにHashMapを使ってくれと言わんばかりの問題です。
コード例を見る
// https://atcoder.jp/contests/abc231/tasks/abc231_b
use std::collections::HashMap;
fn run(_n: usize, s: Vec<&str>) -> String {
let mut map = HashMap::new();
for name in s {
let count = map.entry(name).or_insert(0);
*count += 1;
}
map.iter()
.max_by(|a, b| a.1.cmp(b.1))
.unwrap()
.0.to_string()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(String::from("takahashi"), run(5, vec!["snuke", "snuke", "takahashi", "takahashi", "takahashi"]));
assert_eq!(String::from("takahashi"), run(5, vec!["takahashi", "takahashi", "aoki", "takahashi", "snuke"]));
assert_eq!(String::from("a"), run(1, vec!["a"]));
}
}
ABC241 B - Pasta
B - Pasta(Difficulty : 42)
コード例を見る
// https://atcoder.jp/contests/abc241/tasks/abc241_b
use std::collections::HashMap;
fn run(n: usize, m: usize, a: Vec<usize>, b: Vec<usize>) -> String {
// 各長さのパスタが何本あるかのHashMap
let mut hash_map_a = HashMap::new();
for num in a {
*hash_map_a.entry(num).or_insert(0) += 1;
}
for num in b {
// numの長さの麺が残り0か、そもそも無ければNoを返す
if *hash_map_a.get(&num).unwrap_or(&0) == 0 {
return String::from("No")
} else {
*hash_map_a.entry(num).or_insert(0) -= 1;
}
}
String::from("Yes")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(String::from("Yes"), run(3, 2, vec![1, 1, 3], vec![3, 1]));
assert_eq!(String::from("No"), run(1, 1, vec![1000000000], vec![1]));
assert_eq!(String::from("No"), run(5, 2, vec![1, 2, 3, 4, 5], vec![5, 5]));
}
}
ABC155 C - Poll
C - Poll(Difficulty : 236)
コード例を見る
// https://atcoder.jp/contests/abc155/tasks/abc155_c
use std::collections::HashMap;
fn run(_n: usize, h: Vec<&str>) -> Vec<String> {
let mut hash_map = HashMap::new();
for s in h {
*hash_map.entry(s).or_insert(0) += 1;
}
let max_value = hash_map.values().max().unwrap();
let mut ans = hash_map.iter()
.filter(|e| e.1 == max_value)
.map(|e| e.0.to_string())
.collect::<Vec<String>>();
ans.sort();
ans
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(vec!["beet", "vet"], run(7, vec!["beat", "vet", "beet", "bed", "vet", "bet", "beet"]));
assert_eq!(vec!["buffalo"], run(8, vec!["buffalo", "buffalo", "buffalo", "buffalo", "buffalo", "buffalo", "buffalo", "buffalo"]));
assert_eq!(vec!["kick"], run(7, vec!["bass", "bass", "kick", "kick", "bass", "kick", "kick"]));
assert_eq!(vec!["kun", "nichia", "tapu", "ushi"], run(4, vec!["ushi", "tapu", "nichia", "kun"]));
}
}
ABC261 C - NewFolder(1)
C - NewFolder(1)(Difficulty : 179)
コード例を見る
// https://atcoder.jp/contests/abc261/tasks/abc261_c
use std::collections::HashMap;
fn run(_n: usize, s: Vec<&str>) -> Vec<String> {
let mut hash_map = HashMap::new();
let mut ans = Vec::new();
for str in s {
match hash_map.get(str) {
Some(num) => {
let s = format!("{}({})", str, num);
ans.push(s);
},
None => {
ans.push(str.to_string());
}
}
*hash_map.entry(str.to_string()).or_insert(0) += 1;
}
ans
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, Vec<&'static str>, Vec<&'static str>);
#[test]
fn test() {
let tests = [
TestCase(5, vec!["newfile", "newfile", "newfolder", "newfile", "newfolder"], vec!["newfile", "newfile(1)", "newfolder", "newfile(2)", "newfolder(1)"]),
TestCase(11, vec!["a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a"], vec!["a", "a(1)", "a(2)", "a(3)", "a(4)", "a(5)", "a(6)", "a(7)", "a(8)", "a(9)", "a(10)"]),
];
for TestCase(n, s, expected) in tests {
assert_eq!(expected, run(n, s));
}
}
}
ABC235 C - The Kth Time Query
C - The Kth Time Query(Difficulty : 249)
コード例を見る
// https://atcoder.jp/contests/abc235/tasks/abc235_c
use std::collections::HashMap;
fn run(_n: usize, _q: usize, a: Vec<usize>, xk: Vec<(usize, usize)>) -> Vec<isize> {
let mut hash_map = HashMap::new();
for (i, n) in a.iter().enumerate() {
hash_map.entry(n).or_insert(Vec::new()).push(i+1);
}
xk.into_iter()
.map(|(x, k)| {
if let Some(arr) = hash_map.get(&x) {
if let Some(i) = arr.get(k-1) {
*i as isize
} else {
-1
}
} else {
-1
}
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, Vec<usize>, Vec<(usize, usize)>, Vec<isize>);
#[test]
fn test() {
let tests = [
TestCase(6, 8, vec![1, 1, 2, 3, 1, 2], vec![(1, 1), (1, 2), (1, 3), (1, 4), (2, 1), (2, 2), (2, 3), (4, 1)], vec![1, 2, 5, -1, 3, 6, -1, -1]),
TestCase(3, 2, vec![0, 1000000000, 999999999], vec![(1000000000, 1), (123456789, 1)], vec![2, -1]),
];
for TestCase(n, q, a, xk, expected) in tests {
assert_eq!(run(n, q, a, xk), expected);
}
}
}
ABC210 C - Colorful Candies
C - Colorful Candies(Difficulty : 359)
コード例を見る
// https://atcoder.jp/contests/abc210/tasks/abc210_c
use std::collections::HashMap;
fn run(n: usize, k: usize, c: Vec<usize>) -> usize {
let mut hash_map = HashMap::new();
for num in &c[0..k] {
*hash_map.entry(num).or_insert(0) += 1;
}
let mut ans = hash_map.len();
for i in k..n {
*hash_map.entry(&c[i]).or_insert(0) += 1;
if let Some(count) = hash_map.get_mut(&c[i-k]) {
*count -= 1;
if *count == 0 {
hash_map.remove(&c[i-k]);
}
ans = ans.max(hash_map.len());
}
}
ans
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, Vec<usize>, usize);
#[test]
fn test() {
let tests = [
TestCase(7, 3, vec![1, 2, 1, 2, 3, 3, 1], 3),
TestCase(5, 5, vec![4, 4, 4, 4, 4], 1),
TestCase(10, 6, vec![304621362, 506696497, 304621362, 506696497, 834022578, 304621362, 414720753, 304621362, 304621362, 414720753], 4),
];
for TestCase(n, k, c, expected) in tests {
assert_eq!(run(n, k, c), expected);
}
}
}
ABC194 C - Squared Error
C - Squared Error(Difficulty : 386)
コード例を見る
// https://atcoder.jp/contests/abc194/tasks/abc194_c
use std::collections::HashMap;
fn run(_n: usize, a: Vec<isize>) -> isize {
let mut hash_map = HashMap::new();
for i in a {
*hash_map.entry(i).or_insert(0) += 1;
}
let vec: Vec<(isize, usize)> = hash_map.into_iter().collect();
let mut ans = 0;
for i in 0..vec.len() {
for j in i+1..vec.len() {
ans += (vec[i].0 - vec[j].0).pow(2) * vec[i].1 as isize * vec[j].1 as isize;
}
}
ans
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, Vec<isize>, isize);
#[test]
fn test() {
let tests = [
TestCase(3, vec![2, 8, 4], 56),
TestCase(5, vec![-5, 8, 9, -4, -3], 950),
];
for TestCase(n, a, expected) in tests {
assert_eq!(run(n, a), expected);
}
}
}
ABC278 D - All Assign Point Add
D - All Assign Point Add(Difficulty : 559)
コード例を見る
// https://atcoder.jp/contests/abc278/tasks/abc278_d
use std::collections::HashMap;
fn run(n: usize, a: Vec<usize>, _q: usize, q_vec: Vec<(usize, Option<usize>, Option<usize>)>) -> Vec<usize> {
let mut hash_map = HashMap::new();
for i in 1..=n {
hash_map.insert(i, a[i-1]);
}
let mut base = 0;
let mut ans: Vec<usize> = Vec::new();
for (a, b, c) in q_vec.iter() {
match a {
1 => {
base = b.unwrap();
hash_map.clear()
},
2 => {
hash_map.entry(b.unwrap())
.and_modify(|n| {
*n += c.unwrap();
})
.or_insert(c.unwrap());
},
3 => {
ans.push(base + hash_map.get(&(b.unwrap())).unwrap_or(&0));
},
_ => unreachable!(),
}
}
ans
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, Vec<usize>, usize, Vec<(usize, Option<usize>, Option<usize>)>, Vec<usize>);
#[test]
fn test() {
let tests = [
TestCase(5, vec![3, 1, 4, 1, 5], 6, vec![(3, Some(2), None), (2, Some(3), Some(4)), (3, Some(3), None), (1, Some(1), None), (2, Some(3), Some(4)), (3, Some(3), None)], vec![1, 8, 5]),
TestCase(1, vec![1000000000], 8, vec![(2, Some(1),Some(1000000000)), (2, Some(1), Some(1000000000)), (2, Some(1), Some(1000000000)), (2, Some(1), Some(1000000000)), (2, Some(1), Some(1000000000)), (2, Some(1), Some(1000000000)), (2, Some(1), Some(1000000000)), (3, Some(1), None)], vec![8000000000]),
TestCase(10, vec![1, 8, 4, 15, 7, 5, 7, 5, 8, 0], 20, vec![(2, Some(7), Some(0)), (3, Some(7), None), (3, Some(8), None), (1, Some(7), None), (3, Some(3), None), (2, Some(4), Some(4)), (2, Some(4), Some(9)), (2, Some(10), Some(5)), (1, Some(10), None), (2, Some(4), Some(2)), (1, Some(10), None), (2, Some(3), Some(1)), (2, Some(8), Some(11)), (2, Some(3), Some(14)), (2, Some(1), Some(9)), (3, Some(8), None), (3, Some(8), None), (3, Some(1), None), (2, Some(6), Some(5)), (3, Some(7), None)], vec![7, 5, 7, 21, 21, 19, 10]),
];
for TestCase(n, a, q, q_vec, expected) in tests {
assert_eq!(run(n, a, q, q_vec), expected);
}
}
}
HashSet
ABC166 B - Trick or Treat
B - Trick or Treat(Difficulty : 84)
コード例を見る
// https://atcoder.jp/contests/abc166/tasks/abc166_b
use std::collections::HashSet;
fn run(n: usize, _k: usize, vec: Vec<(usize, Vec<usize>)>) -> usize {
let mut hash_set = HashSet::new();
for v in vec {
for num in v.1 {
hash_set.insert(num);
}
}
(1..=n)
.filter(|num| {
!hash_set.contains(num)
})
.count()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(1, run(3, 2, vec![(2, vec![1, 3]), (1, vec![3])]));
assert_eq!(2, run(3, 3, vec![(1, vec![3]), (1, vec![3]), (1, vec![3])]));
}
}
ABC226 B - Counting Arrays
B - Counting Arrays(Difficulty : 192)
コード例を見る
// https://atcoder.jp/contests/abc232/tasks/abc232_b
use std::collections::HashSet;
fn next_char(c: char, n: u8) -> char {
let val = (c as u8 - 97 + n) % 26 + 97;
val as char
}
fn run(s: &str, t: &str) -> String {
if (0..26)
.any(|i| {
let str: String = s.chars().map(|c| next_char(c, i)).collect();
str == t
}) {
String::from("Yes")
} else {
String::from("No")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(String::from("Yes"), run("abc", "ijk"));
assert_eq!(String::from("Yes"), run("z", "a"));
assert_eq!(String::from("No"), run("ppq", "qqp"));
assert_eq!(String::from("Yes"), run("atcoder", "atcoder"));
}
}
ABC251 C - Poem Online Judge
C - Poem Online Judge(Difficulty : 246)
コード例を見る
// https://atcoder.jp/contests/abc251/tasks/abc251_c
use std::collections::HashSet;
fn run(_n: usize, st: Vec<(&str, usize)>) -> usize {
let mut hash_set = HashSet::new();
let mut pos = 0;
let mut score = 0;
for (i, (s, t)) in st.into_iter().enumerate() {
if hash_set.contains(&s) {
continue;
}
hash_set.insert(s);
if t > score {
pos = i+1;
score = t;
}
}
pos
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, Vec<(&'static str, usize)>, usize);
#[test]
fn test() {
let tests = [
TestCase(3, vec![("aaa", 10), ("bbb", 20), ("aaa", 30)], 2),
];
for TestCase(n, st, expected) in tests {
assert_eq!(run(n, st), expected);
}
}
}
ABC278 C - FF
C - FF(Difficulty : 327)
コード例を見る
// https://atcoder.jp/contests/abc278/tasks/abc278_c
use std::collections::HashSet;
fn run(_n: usize, _q: usize, tab: Vec<(usize, usize, usize)>) -> Vec<&'static str> {
let mut hash_set = HashSet::new();
tab.into_iter()
.filter_map(|(t, a, b)| {
match t {
1 => {
hash_set.insert((a, b));
None
},
2 => {
hash_set.remove(&(a, b));
None
},
3 => {
if hash_set.contains(&(a, b)) && hash_set.contains(&(b, a)) {
Some("Yes")
} else {
Some("No")
}
},
_ => unreachable!(),
}
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, Vec<(usize, usize, usize)>, Vec<&'static str>);
#[test]
fn test() {
let tests = [
TestCase(3, 9, vec![(1, 1, 2), (3, 1, 2), (1, 2, 1), (3, 1, 2), (1, 2, 3), (1, 3, 2), (3, 1, 3), (2, 1, 2), (3, 1, 2)], vec!["No", "Yes", "No", "No"]),
TestCase(2, 8, vec![(1, 1, 2), (1, 2, 1), (3, 1, 2), (1, 1, 2), (1, 1, 2), (1, 1, 2), (2, 1, 2), (3, 1, 2)], vec!["Yes", "No"]),
TestCase(10, 30, vec![(3, 1, 6), (3, 5, 4), (1, 6, 1), (3, 1, 7), (3, 8, 4), (1, 1, 6), (2, 4, 3), (1, 6, 5), (1, 5, 6), (1, 1, 8), (1, 8, 1), (2, 3, 10), (1, 7, 6), (3, 5, 6), (1, 6, 7), (3, 6, 7), (1, 9, 5), (3, 8, 6), (3, 3, 8), (2, 6, 9), (1, 7, 1), (3, 10, 8), (2, 9, 2), (1, 10, 9), (2, 6, 10), (2, 6, 8), (3, 1, 6), (3, 1, 8), (2, 8, 5), (1, 9, 10)], vec!["No", "No", "No", "No", "Yes", "Yes", "No", "No", "No", "Yes", "Yes"]),
];
for TestCase(n, q, tab, expected) in tests {
assert_eq!(run(n, q, tab), expected);
}
}
}
BTreeSet
ABC352 D - Permutation Subsequence
D - Permutation Subsequence(Difficulty : 714)
コード例を見る
// https://atcoder.jp/contests/abc352/tasks/abc352_d
use std::collections::BTreeSet;
fn run(n: usize, k: usize, p: Vec<usize>) -> usize {
let mut vec = vec![0; n];
for (i, num) in p.iter().enumerate() {
vec[num-1] = i+1;
}
let mut btree_set = BTreeSet::new();
let mut ans = std::usize::MAX;
for num in vec.iter().take(k) {
btree_set.insert(num);
}
for i in 0..n {
if i >= k {
btree_set.remove(&vec[i-k]);
}
btree_set.insert(&vec[i]);
ans = ans.min(**btree_set.last().unwrap() - **btree_set.first().unwrap());
}
ans
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, Vec<usize>, usize);
#[test]
fn test() {
let tests = [
TestCase(4, 2, vec![2, 3, 1, 4], 1),
TestCase(4, 1, vec![2, 3, 1, 4], 0),
TestCase(10, 5, vec![10, 1, 6, 8, 7, 2, 5, 9, 3, 4], 5),
];
for TestCase(n, k, p, expected) in tests {
assert_eq!(run(n, k, p), expected);
}
}
}
BTreeMap
ABC253 C - Max - Min Query
C - Max - Min Query(Difficulty : 518)
コード例を見る
// https://atcoder.jp/contests/abc253/tasks/abc253_c
use std::collections::BTreeMap;
use std::cmp::min;
fn run(_q: usize, query: Vec<(usize, Option<usize>, Option<usize>)>) -> Vec<usize> {
let mut bt = BTreeMap::new();
let mut ans = Vec::new();
for tup in query.iter() {
match tup {
(1, Some(b), None) => {
*bt.entry(b).or_insert(0) += 1;
},
(2, Some(b), Some(c)) => {
if let Some(value) = bt.get_mut(b) {
let subtract_amount = min(*value, *c);
*value -= subtract_amount;
if *value == 0 {
bt.remove(b);
}
}
},
(3, None, None) => {
ans.push(*bt.iter().next_back().unwrap().0 - *bt.iter().next().unwrap().0);
},
_ => unreachable!(),
}
}
ans
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, Vec<(usize, Option<usize>, Option<usize>)>, Vec<usize>);
#[test]
fn test() {
let tests = [
TestCase(8, vec![(1, Some(3), None), (1, Some(2), None), (3, None, None), (1, Some(2), None), (1, Some(7), None), (3, None, None), (2, Some(2), Some(3)), (3, None, None)], vec![1, 5, 4]),
TestCase(4, vec![(1, Some(10000), None), (1, Some(1000), None), (2, Some(100), Some(3)), (1, Some(10), None)], vec![]),
];
for TestCase(q, query, expected) in tests {
assert_eq!(run(q, query), expected);
}
}
}
その他
アルゴリズムやデータ構造ではないですが、様々なテーマで問題を分類しました。
文字列操作
ABC232 B - Caesar Cipher
B - Caesar Cipher(Difficulty : 82)
コード例を見る
// https://atcoder.jp/contests/abc232/tasks/abc232_b
fn next_char(c: char, n: u8) -> char {
let val = (c as u8 - 97 + n) % 26 + 97;
val as char
}
fn run(s: &str, t: &str) -> String {
if (0..26)
.any(|i| {
let str: String = s.chars().map(|c| next_char(c, i)).collect();
str == t
}) {
String::from("Yes")
} else {
String::from("No")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(String::from("Yes"), run("abc", "ijk"));
assert_eq!(String::from("Yes"), run("z", "a"));
assert_eq!(String::from("No"), run("ppq", "qqp"));
assert_eq!(String::from("Yes"), run("atcoder", "atcoder"));
}
}
最小公倍数
ABC148 C - Snack
C - Snack(Difficulty : 82)
コード例を見る
// https://atcoder.jp/contests/abc148/tasks/abc148_c
fn gcd(m: usize, n: usize) -> usize {
if n == 0 {
m
} else {
gcd(n, m % n)
}
}
fn run(a: usize, b: usize) -> usize {
a / gcd(a, b) * b
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test () {
assert_eq!(6, run(2, 3));
assert_eq!(18696, run(123, 456));
assert_eq!(9999900000, run(100000, 99999));
}
}
ARC110 A - Redundant Redundancy
A - Redundant Redundancy(Difficulty : 120)
コード例を見る
// https://atcoder.jp/contests/arc110/tasks/arc110_a
fn gcd(m: usize, n: usize) -> usize {
if n == 0 {
m
} else {
gcd(n, m % n)
}
}
fn run(n: usize) -> usize {
let mut num = 1;
for i in 2..=n {
num = num / gcd(num, i) * i;
}
num + 1
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize);
#[test]
fn test() {
let tests = [
TestCase(3, 7),
TestCase(10, 2521),
];
for TestCase(n, expected) in tests {
assert_eq!(run(n), expected);
}
}
}
回文判定
競技プログラミングの鉄則 B56 - Palindrome Queries
コード例を見る
// https://atcoder.jp/contests/tessoku-book/tasks/tessoku_book_ec
fn check(s: &str) -> bool {
s.chars().eq(s.chars().rev())
}
fn run(_n: usize, _q: usize, s: &str, vec: Vec<(usize, usize)>) -> Vec<String> {
vec.iter().map(|v| {
if check(&s[(v.0 - 1)..=(v.1 - 1)]) {
String::from("Yes")
} else {
String::from("No")
}
}).collect::<Vec<String>>()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(vec![String::from("Yes"), String::from("No"), String::from("Yes")], run(11, 3, "mississippi", vec![(5, 8), (6, 10), (2, 8)]));
}
}
ABC066 B - ss
B - ss(Difficulty : 384)
コード例を見る
// https://atcoder.jp/contests/abc066/tasks/abc066_b
fn check(s: &str) -> bool {
if s[0..s.len()/2] == s[s.len()/2..] {
true
} else {
false
}
}
fn run(s: String) -> usize {
(0..s.len())
.rev()
.skip(1)
.step_by(2)
.find(|i| {
check(&s[0..*i])
}).unwrap()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(6, run(String::from("abaababaab")));
assert_eq!(2, run(String::from("xxxx")));
assert_eq!(6, run(String::from("abcabcabcabc")));
assert_eq!(14, run(String::from("akasakaakasakasakaakas")));
}
}
ABC147 B - Palindrome-philia
B - Palindrome-philia(Difficulty : 44)
コード例を見る
fn run(s: &str) -> usize {
let chars: Vec<char> = s.chars().collect();
(0..chars.len()/2).filter(|i| {
chars[*i] != chars[s.len() - *i - 1]
}).count()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(1, run("redcoder"));
assert_eq!(0, run("wwwww"));
assert_eq!(1, run("rng"));
assert_eq!(50, run("ndfzvmkpudjeocebkfpexoszwczmpbdmivjnfeqapwvmbiiiarpwrjyezwdgydqbldyfyslboertiilckvacvroxycczmpfmdymu"));
assert_eq!(10, run("aybmyzzankubfabovxfkoazziskrl"));
assert_eq!(1, run("ax"));
assert_eq!(0, run("xxx"));
assert_eq!(34, run("uqoppvgpiqmsiwhpyfqnilmqkokdzowhrkzlavboipnljjlljpjwqalvxfvwpuairhxqiioqflgcwxvjupvghpadng"));
assert_eq!(2, run("hjvqwycocvwqvth"));
assert_eq!(34, run("xzamzvhfwhndreischtcucykbfjqasqlbkoxjpglbppptrvfccnfvlzppgdlmmseoidlqschqwnkfvqptsriiorvfqdjhrumjfc"));
}
}
ABC307 B - racecar
B - racecar(Difficulty : 70)
コード例を見る
fn check(s: String) -> bool {
s.chars().eq(s.chars().rev())
}
fn run(_n: usize, s: Vec<&str>) -> String {
if s.iter()
.permutations(2)
.any(|v| check(format!("{}{}", v[0], v[1])))
{
String::from("Yes")
} else {
String::from("No")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(String::from("Yes"), run(5, vec!["ab", "ccef", "da", "a", "fe"]));
assert_eq!(String::from("No"), run(3, vec!["a", "b", "aba"]));
assert_eq!(String::from("Yes"), run(2, vec!["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]));
}
}
ABC198 B - Palindrome with leading zeros
B - Palindrome with leading zeros(Difficulty : 96)
先頭に好きなだけ0
を付けれるという事は、末尾の0
を全て削除できると同じと捉えられます。
コード例を見る
// https://atcoder.jp/contests/abc198/tasks/abc198_b
fn check(s: &str) -> bool {
s.chars().eq(s.chars().rev())
}
fn run(n: usize) -> String {
if n == 0 {
return String::from("Yes");
}
let mut num = n;
// numの末尾0を取り除く
// (10で割り切れる限り割る)
while num % 10 == 0 {
num /= 10
}
if check(&num.to_string()) {
String::from("Yes")
} else {
String::from("No")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(String::from("Yes"), run(1210));
assert_eq!(String::from("Yes"), run(12100000000));
assert_eq!(String::from("Yes"), run(777));
assert_eq!(String::from("No"), run(123456789));
}
}
ABC237 C - kasaka
C - kasaka(Difficulty : 267)
コード例を見る
// https://atcoder.jp/contests/abc237/tasks/abc237_c
fn check(s: String) -> bool {
s.chars().eq(s.chars().rev())
}
// Refactoring
fn run(s: String) -> &'static str {
// 先頭、末尾から連続して何文字aが続くかをカウント
let mut head = 0;
let mut tail = 0;
for c in s.chars() {
if c == 'a' {
head += 1;
} else {
break
}
}
for c in s.chars().rev() {
if c == 'a' {
tail += 1;
} else {
break
}
}
// 先頭のaの方が多い時
if head > tail {
return "No"
}
// 全てaの時
if head == s.len() {
return "Yes"
}
let mut vec: Vec<char> = s.chars().collect();
// 先頭と末尾の連続するaを削除
vec.drain(0..head);
vec.drain((vec.len()-tail)..vec.len());
let str: String = vec.iter().collect();
if check(str) {
"Yes"
} else {
"No"
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
assert_eq!(String::from("Yes"), run(String::from("kasaka")));
assert_eq!(String::from("No"), run(String::from("atcoder")));
assert_eq!(String::from("Yes"), run(String::from("php")));
assert_eq!(String::from("Yes"), run(String::from("aaaaaaaa")));
assert_eq!(String::from("Yes"), run(String::from("aaabaaa")));
assert_eq!(String::from("No"), run(String::from("aaaabaaa")));
assert_eq!(String::from("Yes"), run(String::from("aaabaaaa")));
}
}
ABC363 C - Avoid K Palindrome 2
C - Avoid K Palindrome 2 (Difficulty : 602)
コード例を見る
// https://atcoder.jp/contests/abc363/tasks/abc363_c
use itertools::Itertools;
use std::collections::HashSet;
fn check(chars: &[char]) -> bool {
chars.iter().eq(chars.iter().rev())
}
fn run(n: usize, k: usize, s: &str) -> usize {
let chars: Vec<char> = s.chars().collect();
// 文字列の重複を防ぐ
let mut hash_set: HashSet<Vec<char>> = HashSet::new();
for str in chars.into_iter().permutations(n) {
hash_set.insert(str);
}
let mut ans = 0;
'outer: for str in hash_set.into_iter() {
// k文字の部分文字列生成
for arr in str.windows(k) {
// 部分文字列に一つでも回文があったら次の文字に進む
if check(arr) == true {
continue 'outer;
}
}
ans += 1;
}
ans
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, &'static str, usize);
#[test]
fn test() {
let tests = [
TestCase(3, 2, "aab", 1),
TestCase(5, 3, "zzyyx", 16),
TestCase(10, 5, "abcwxyzyxw", 440640),
];
for TestCase(n, k, s, expected) in tests {
assert_eq!(run(n, k, s), expected);
}
}
}
n進数
ABC336 C - Even Digits
C - Even Digits(Difficulty : 343)
コード例を見る
// https://atcoder.jp/contests/abc336/tasks/abc336_c
fn calc(num: usize, mut result: Vec<usize>) -> Vec<usize> {
if num == 0 {
result
} else {
result.push(num % 5);
calc(num / 5, result)
}
}
fn run(n: usize) -> usize {
let mut vec = calc(n-1, Vec::new());
vec.reverse();
vec.iter()
.fold(0, |state, num| {
state * 10 + num * 2
})
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize);
#[test]
fn test() {
let tests = [
TestCase(8, 24),
TestCase(133, 2024),
TestCase(31415926535, 2006628868244228),
];
for TestCase(n, expected) in tests {
assert_eq!(expected, run(n));
}
}
}
周期性
ABC165 D - Floor Function
D - Floor Function(Difficulty : 600)
コード例を見る
// https://atcoder.jp/contests/abc165/tasks/abc165_d
use std::cmp::min;
fn run(a: f64, b: f64, n: f64) -> usize {
let x = f64::min(b - 1.0, n) as f64;
((a*x/b).floor() - a * (x/b).floor()) as usize
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(f64, f64, f64, usize);
#[test]
fn test() {
let tests = [
TestCase(5.0, 7.0, 4.0, 2),
TestCase(11.0, 10.0, 9.0, 9),
];
for TestCase(a, b, n, expected) in tests {
assert_eq!(run(a, b, n), expected);
}
}
}
後から帳尻合わせる系
その都度リスト操作してると間に合わないので、操作状況を記録しておいて出力時に帳尻合わせるというか。C問題に多いイメージ。
ABC258 C - Rotation
C - Rotation(Difficulty : 419)
コード例を見る
// https://atcoder.jp/contests/abc258/tasks/abc258_c
fn run(n: usize, _q: usize, s: &str, query: Vec<(usize, usize)>) -> Vec<char> {
let vec: Vec<char> = s.chars().collect();
let mut count = 0;
let mut ans = Vec::new();
for (t, x) in query {
match t {
1 => {
count += x;
},
2 => {
if x < count {
count %= n;
}
ans.push(vec[(x + n - count - 1) % n]);
},
_ => unreachable!(),
}
}
ans
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(usize, usize, &'static str, Vec<(usize, usize)>, Vec<char>);
#[test]
fn test() {
let tests = [
TestCase(3, 3, "abc", vec![(2, 2), (1, 1), (2, 2)], vec!['b', 'a']),
TestCase(10, 8, "dsuccxulnl", vec![(2, 4), (2, 7), (1, 2), (2, 7), (1, 1), (1, 2), (1, 3), (2, 5)], vec!['c', 'u', 'c', 'u']),
];
for TestCase(n, q, s, query, expected) in tests {
assert_eq!(run(n, q, s, query), expected);
}
}
}
ABC158 D - String Formation
D - String Formation(Difficulty : 610)
コード例を見る
// https://atcoder.jp/contests/abc158/tasks/abc158_d
use std::collections::VecDeque;
fn run(s: &str, _n: usize, query: Vec<(usize, Option<usize>, Option<char>)>) -> String {
let mut ans = VecDeque::new();
for c in s.chars() {
ans.push_back(c);
}
let mut flag = true;
for q in query.iter() {
match q.0 {
1 => {
flag = !flag;
},
2 => {
let p = q.1.unwrap();
let c = q.2.unwrap();
if p == 1 {
if flag {
ans.push_front(c);
} else {
ans.push_back(c);
}
} else {
if flag {
ans.push_back(c);
} else {
ans.push_front(c);
}
}
},
_ => unreachable!(),
}
}
if flag {
ans.into_iter().collect::<String>()
} else {
ans.into_iter().rev().collect::<String>()
}
}
#[cfg(test)]
mod tests {
use super::*;
struct TestCase(&'static str, usize, Vec<(usize, Option<usize>, Option<char>)>, &'static str);
#[test]
fn test() {
let tests = [
TestCase("a", 4, vec![(2, Some(1), Some('p')), (1, None, None), (2, Some(2), Some('c')), (1, None, None)], "cpa"),
TestCase("a", 6, vec![(2, Some(2), Some('a')), (2, Some(1), Some('b')), (1, None, None), (2, Some(2), Some('c')), (1, None, None), (1, None, None)], "aabc"),
TestCase("y", 1, vec![(2, Some(1), Some('x'))], "xy"),
];
for TestCase(s, n, query, expected) in tests {
assert_eq!(run(s, n, query), expected);
}
}
}
更新履歴
- 2025年03月23日 : ABC396 D - Minimum XOR Pathを追加
- 2025年03月14日 : ABC283 D - Scopeを追加
- 2025年03月11日 : ABC258 C - Rotationを追加
- 2025年03月08日 : ABC276 E - Round Tripを追加
- 2025年02月21日 : ABC015 🧪 C - 高橋くんのバグ探しを追加
- 2025年02月19日 : ABC373 D - Hidden Weightsを追加
- 2025年02月18日 : ABC376 D - Cycleを追加
- 2025年02月15日 : ABC383 C - Humidifier 3を追加
- 2025年02月09日 : ABC293 C - Make Takahashi Happyを追加
- 2025年02月08日 : ABC387 D - Snaky Walkを追加
- 2025年02月01日 : 競技プログラミングの鉄則 A63 - Shortest Path 1を追加
- 2025年01月30日 : ABC168 D - .. (Double Dots)を追加
- 2025年01月29日 : ABC151 D - Maze Masterを追加
- 2025年01月28日 : ABC325 C - Sensorsを追加
- 2025年01月25日 : ABC269 D - Do use hexagon gridを追加
- 2025年01月16日 : ABC211 D - Number of Shortest pathsを追加
- 2025年01月14日 : ABC088 D - Grid Repaintingを追加
- 2025年01月13日 : ABC016 C - 友達の友達を追加
- 2025年01月12日 : ABC388 C - Various Kagamimochiを追加