今日解いた問題
E - Prefix-free Game
実験によって grundy 数を求めるのはよく見る気がする。
use std::collections::{BTreeMap, BTreeSet}; fn main() { let s = std::io::stdin(); let mut sc = Scanner { stdin: s.lock() }; let n: usize = sc.read(); let l: u64 = sc.read(); let mut trie = Trie { nodes: vec![[0; 2]], }; for _ in 0..n { let s: Vec<usize> = sc .chars() .into_iter() .map(|c| c as usize - '0' as usize) .collect(); trie.add(&s, 0, 0); } let mut results = vec![]; trie.traverse(0, &mut results, l); println!( "{}", if results .into_iter() .map(|h| 1 << h.trailing_zeros()) .fold(0, |xor, x| xor ^ x) == 0 { "Bob" } else { "Alice" } ); } struct Trie { nodes: Vec<[usize; 2]>, } impl Trie { fn add(&mut self, s: &[usize], pos: usize, cur: usize) { if pos == s.len() { return; } if self.nodes[cur][s[pos]] == 0 { self.nodes[cur][s[pos]] = self.nodes.len(); self.nodes.push([0; 2]); } let cur = self.nodes[cur][s[pos]]; self.add(s, pos + 1, cur); } fn traverse(&self, cur: usize, results: &mut Vec<u64>, height: u64) { let (a, b) = (self.nodes[cur][0], self.nodes[cur][1]); if a == 0 && b == 0 { return; } if a == 0 || b == 0 { results.push(height); } if a != 0 { self.traverse(a, results, height - 1); } if b != 0 { self.traverse(b, results, height - 1); } } } fn grundy(l: usize, map: &mut BTreeMap<usize, usize>) -> usize { match map.get(&l) { Some(&x) => x, None => { let mut set = BTreeSet::new(); for i in 1..(l + 1) { let mut g = 0; for j in 1..i { g ^= grundy(l - j, map); } set.insert(g); } let g = (0..).find(|x| !set.contains(x)).unwrap(); map.insert(l, g); g } } } pub struct Scanner<R> { stdin: R, } impl<R: std::io::Read> Scanner<R> { pub fn read<T: std::str::FromStr>(&mut self) -> T { use std::io::Read; let buf = self .stdin .by_ref() .bytes() .map(|b| b.unwrap()) .skip_while(|&b| b == b' ' || b == b'\n' || b == b'\r') .take_while(|&b| b != b' ' && b != b'\n' && b != b'\r') .collect::<Vec<_>>(); unsafe { std::str::from_utf8_unchecked(&buf) } .parse() .ok() .expect("Parse error.") } pub fn vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> { (0..n).map(|_| self.read()).collect() } pub fn chars(&mut self) -> Vec<char> { self.read::<String>().chars().collect() } }