結果
| 問題 |
No.3342 AAB Game
|
| コンテスト | |
| ユーザー |
Solalyth
|
| 提出日時 | 2025-11-13 22:47:13 |
| 言語 | Rust (1.83.0 + proconio) |
| 結果 |
AC
|
| 実行時間 | 3 ms / 2,000 ms |
| コード長 | 16,239 bytes |
| コンパイル時間 | 12,435 ms |
| コンパイル使用メモリ | 400,412 KB |
| 実行使用メモリ | 7,716 KB |
| 最終ジャッジ日時 | 2025-11-13 22:47:31 |
| 合計ジャッジ時間 | 14,202 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 39 |
ソースコード
#![allow(unused_must_use, non_snake_case, unused_labels, unused_imports, non_upper_case_globals)]
use external::*;
use cplib::prelude::*;
use nest as vec;
const INTERACTIVE: bool = false;
// const INTERACTIVE: bool = true; use input_interactive as input;
fn solve() {
input! { _: usize, S: chars }
let mut cur = 0;
for c in S {
cur *= 2;
if c == 'B' {
cur += 1;
}
cur %= 3;
}
out << ["Bob", "Alice", "Alice"][cur];
}
fn main() { out::init(INTERACTIVE || !SUBMISSION); solve(); out::print() }
mod external { pub use { proconio::{ input, input_interactive, marker::{Chars as chars, Usize1 as usize1} }, }; }
// my library: https://github.com/solalyth/cplib-rs
mod cplib { #![allow(unused_macros, dead_code)] pub const SUBMISSION: bool = true; pub mod prelude { pub use std::{ collections::{VecDeque, HashMap, HashSet, BTreeMap, BTreeSet, BinaryHeap}, cmp::{Ordering, Reverse}, mem::{swap, replace} }; pub use crate::cplib::{ *, SUBMISSION, ds::segtree::SegtreeOp, util::{ output::{out, end}, traits::* }, }; use std::fmt; #[derive(Clone, Copy, PartialEq, PartialOrd)] pub struct F64(pub f64); impl Eq for F64 {} impl Ord for F64 { fn cmp(&self, other: &Self) -> Ordering { self.partial_cmp(other).unwrap() } } impl fmt::Debug for F64 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.0) } } } pub mod debug { pub fn replace_inf(s: &str) -> String { let (mut res, mut stk) = (String::new(), String::new()); for c in s.chars().chain(std::iter::once('*')) { if c.is_numeric() || c == '.' { stk.push(c); continue; } if stk.parse::<f64>().map_or(false, |s| 1.15e18 <= s) { res += "inf"; } else { res += &stk; } stk.clear(); res.push(c); } res.pop(); res } #[macro_export] macro_rules! epr { ($($args:tt)*) => { if !$crate::SUBMISSION { eprintln!("\x1b[31m{}\x1b[0m", crate::debug::replace_inf(&format!($($args)*))); } } } #[macro_export] macro_rules! table { ($vv:expr) => { if !$crate::SUBMISSION { use std::fmt::Write; let (mut lmax, mut res) = (0, String::new()); let vv: Vec<Vec<String>> = $vv.iter().map(|v| v.iter().map(|e| { let t = crate::debug::replace_inf(&format!("{e:?}")); lmax = lmax.max(t.len()); t }).collect()).collect(); for v in &vv { res += " [ "; for e in v { write!(&mut res, "{e: >lmax$}, "); } res.pop(); res.pop(); res += "]\n"; } eprintln!("\x1b[38;5;208m{} = [\n{res}]\x1b[0m", stringify!($vv)); } }; } #[macro_export] macro_rules! oj_local { ($oj:expr, $local:expr) => { if $crate::SUBMISSION { $oj } else { $local } }; } } pub mod ds { pub mod segtree { use std::{fmt::Debug, mem::replace, ops::{Index, IndexMut, RangeBounds}, slice::SliceIndex}; use crate::cplib::util::func::to_bounds; #[allow(unused_variables)] pub trait SegtreeOp: Sized { const BEATS: bool = false; type Value: Clone + Debug; type Lazy: Clone; fn id_value() -> Self::Value; fn prod_value(lhs: &Self::Value, rhs: &Self::Value) -> Self::Value; fn act_value(value: &mut Self::Value, lazy: &Self::Lazy) -> bool { true } fn prod_lazy(lazy: &mut Self::Lazy, ad: &Self::Lazy) {} fn segtree_new(len: usize) -> Segtree<Self> { Segtree::new(len) } fn segtree_from_iter(iter: impl Iterator<Item = Self::Value>) -> Segtree<Self> { Segtree::from_iter(iter) } } pub struct Segtree<Op: SegtreeOp> { tree: Vec<Op::Value>, lazy: Vec<Option<Op::Lazy>>, depth: u32 } impl<Op: SegtreeOp> Segtree<Op> { pub fn new(len: usize) -> Self { let depth = (len.max(2)-1).ilog2() + 2; Segtree { tree: vec![Op::id_value(); 1<<depth], lazy: vec![None; 1<<depth], depth } } pub fn len(&self) -> usize { 1 << self.depth-1 } pub fn get(&mut self, mut i: usize) -> &Op::Value { i += self.len(); for j in (1..self.depth).rev() { self.push(i >> j); } &self.tree[i] } pub fn set(&mut self, mut i: usize, f: impl FnOnce(&mut Op::Value)) { i += self.len(); for j in (1..self.depth).rev() { self.push(i >> j); } f(&mut self.tree[i]); for j in 1..self.depth { self.update(i >> j); } } pub fn entry(&mut self) -> Entry<'_, Op> { for i in 1..self.len() { self.push(i); } Entry { seg: self, changed: false } } pub fn fold(&mut self, range: impl RangeBounds<usize>) -> Op::Value { let [mut l, mut r] = to_bounds(range, self.len()).map(|v| v+self.len()); if r == self.len() { return Op::id_value(); } let (mut rl, mut rr) = (Op::id_value(), Op::id_value()); for i in (1..self.depth).rev() { self.push(l >> i); self.push(r-1 >> i); } while l < r { if l&1 == 1 { rl = Op::prod_value(&rl, &self.tree[l]); l += 1; } if r&1 == 1 { rr = Op::prod_value(&self.tree[r-1], &rr); } l >>= 1; r >>= 1; } Op::prod_value(&rl, &rr) } pub fn apply(&mut self, range: impl RangeBounds<usize>, lazy: Op::Lazy) { let [l, r] = to_bounds(range, self.len()).map(|v| v + self.len()); if r == self.len() { return; } for i in (1..self.depth).rev() { self.push(l >> i); self.push(r-1 >> i); } let (mut s, mut t) = (l, r); while s < t { if s&1 == 1 { self.node_apply(s, &lazy); s += 1; } if t&1 == 1 { t -= 1; self.node_apply(t, &lazy); } s >>= 1; t >>= 1; } for i in 1..self.depth { if ((l >> i) << i) != l { self.update(l >> i); } if ((r >> i) << i) != r { self.update(r-1 >> i); } } } pub fn max_right(&mut self, l: usize, r_max: usize, f: impl Fn(&Op::Value) -> bool) -> usize { assert!(l <= self.len()); if l == self.len() { return self.len().min(r_max); } let (mut r, mut val) = (l + self.len(), Op::id_value()); for i in (1..self.depth).rev() { self.push(r >> i); } loop { while r&1 == 0 { r >>= 1; } let tmp = Op::prod_value(&val, &self.tree[r]); if !f(&tmp) { break; } val = tmp; r += 1; if r & r-1 == 0 { return self.len().min(r_max); } } while r < self.len() { self.push(r); r *= 2; let tmp = Op::prod_value(&val, &self.tree[r]); if f(&tmp) { val = tmp; r += 1; } } (r - self.len()).min(r_max) } pub fn min_left(&mut self, r: usize, f: impl Fn(&Op::Value) -> bool) -> usize { assert!(r <= self.len()); if r == 0 { return 0; } let (mut l, mut val) = (r + self.len(), Op::id_value()); for i in (1..self.depth).rev() { self.push(l-1 >> i); } loop { l -= 1; while l != 1 && l&1 == 1 { l >>= 1; } let tmp = Op::prod_value(&self.tree[l], &val); if !f(&tmp) { break; } val = tmp; if l & l-1 == 0 { return 0; } } while l < self.len() { self.push(l); l = 2*l + 1; let tmp = Op::prod_value(&self.tree[l], &val); if f(&tmp) { val = tmp; l -= 1; } } l+1 - self.len() } fn node_apply(&mut self, i: usize, lazy: &Op::Lazy) { if Op::BEATS { self.comp_lazy(i, lazy); if !Op::act_value(&mut self.tree[i], lazy) { self.push(i); self.update(i); } } else { Op::act_value(&mut self.tree[i], lazy); self.comp_lazy(i, lazy); } } #[track_caller] fn push(&mut self, i: usize) { debug_assert!(i < self.len()); let Some(lazy) = replace(&mut self.lazy[i], None) else { return }; self.node_apply(2*i, &lazy); self.node_apply(2*i+1, &lazy); } fn update(&mut self, i: usize) { debug_assert!(i < self.len()); debug_assert!(self.lazy[i].is_none()); self.tree[i] = Op::prod_value(&self.tree[2*i], &self.tree[2*i+1]); } fn comp_lazy(&mut self, i: usize, ad: &Op::Lazy) { if let Some(lazy) = &mut self.lazy[i] { Op::prod_lazy(lazy, ad); } else { self.lazy[i] = Some(ad.clone()); } } } impl<Op: SegtreeOp> Clone for Segtree<Op> { fn clone(&self) -> Self { Self { tree: self.tree.clone(), lazy: self.lazy.clone(), depth: self.depth.clone() } } } impl<Op: SegtreeOp> Debug for Segtree<Op> where Op::Value: Debug { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let mut seg = self.clone(); for i in 1..seg.len() { seg.push(i); } write!(f, "{:?}", &seg.tree[self.len()..]) } } impl<Op: SegtreeOp> FromIterator<Op::Value> for Segtree<Op> { fn from_iter<T: IntoIterator<Item = Op::Value>>(iter: T) -> Self { let v = iter.into_iter().collect::<Vec<_>>(); let mut seg = Self::new(v.len()); let len = seg.len(); for (i, v) in v.into_iter().enumerate() { seg.tree[len+i] = v; } for i in (1..seg.len()).rev() { seg.update(i); } seg } } pub struct Entry<'a, Op: SegtreeOp> { seg: &'a mut Segtree<Op>, changed: bool } impl<Op: SegtreeOp, I: SliceIndex<[Op::Value]>> Index<I> for Entry<'_, Op> { type Output = I::Output; fn index(&self, index: I) -> &Self::Output { Index::index(&self.seg.tree[self.seg.len()..], index) } } impl<Op: SegtreeOp, I: SliceIndex<[Op::Value]>> IndexMut<I> for Entry<'_, Op> { fn index_mut(&mut self, index: I) -> &mut Self::Output { let len = self.seg.len(); self.changed = true; IndexMut::index_mut(&mut self.seg.tree[len..], index) } } impl<Op: SegtreeOp> Drop for Entry<'_, Op> { fn drop(&mut self) { if self.changed { for i in (1..self.seg.len()).rev() { self.seg.update(i); } } } } } } pub mod algo { } pub mod graph { } pub mod math { } pub mod mod998 { } pub mod util { pub mod output { #![allow(static_mut_refs, non_camel_case_types)] use std::{mem::replace, ops::{Not, Shl}, fmt::Write}; static mut BUFFER: Buffer = Buffer { buf: String::new(), endp: false, prev: Previous::LineHead }; pub struct Buffer { buf: String, endp: bool, prev: Previous, } impl Buffer { const LEN: usize = 16*1024*1024; fn print(&mut self) { if replace(&mut self.prev, Previous::LineHead) == Previous::LineHead { self.buf.pop(); } if crate::cplib::SUBMISSION { println!("{}", self.buf); } else { eprint!("\x1b[32m"); if self.buf.is_empty() { println!(">> (empty)"); } else { for s in self.buf.split('\n') { eprint!(">> "); println!("{s}"); } } eprint!("\x1b[0m"); } self.buf.clear(); } fn space(&mut self, sp: bool) { let prev = replace(&mut self.prev, if sp {Previous::Space} else {Previous::NoSpace}); if (sp || prev == Previous::Space) && prev != Previous::LineHead { self.buf.push(' '); } } } #[derive(Clone, Copy)] pub struct out; pub struct out_usp; pub struct end; #[derive(PartialEq, Eq, Clone, Copy)] enum Previous { Space, NoSpace, LineHead, } impl out { pub fn init(endp: bool) { unsafe { BUFFER.buf.reserve(Buffer::LEN); BUFFER.endp = endp; } } pub fn print() { unsafe { BUFFER.print(); } } pub fn space() { unsafe { if BUFFER.prev == Previous::NoSpace { BUFFER.prev = Previous::Space; } } } fn push<T: Primitive>(v: &T) { unsafe { BUFFER.space(true); v.fmt(&mut BUFFER.buf); } } } impl out_usp { fn push<T: Primitive>(v: &T) { unsafe { BUFFER.space(false); v.fmt(&mut BUFFER.buf); } } } impl Not for out { type Output = out_usp; fn not(self) -> Self::Output { out_usp } } macro_rules! impl_outs { ($($t:ty),+) => { $( impl<T: Primitive> Shl<T> for $t { type Output = Self; fn shl(self, rhs: T) -> Self::Output { Self::push(&rhs); self } } impl Shl<end> for $t { type Output = Self; fn shl(self, _: end) -> Self::Output { unsafe { if BUFFER.endp { BUFFER.print(); } else { BUFFER.buf += "\n"; BUFFER.prev = Previous::LineHead; } } self } } )+ }; } impl_outs!(out, out_usp); macro_rules! impl_for_slices { ($($t:ty),+) => { $(impl_for_slices!($t; out, out_usp);)+ }; ($t:ty; $($u:ty),+) => { $( impl<T: Primitive> Shl<$t> for $u { type Output = Self; fn shl(self, rhs: $t) -> Self::Output { for v in rhs { Self::push(v); } self } } )+} } impl_for_slices!(&[T], &Vec<T>); trait Primitive { fn fmt(&self, buf: &mut String); } macro_rules! impl_primitive { ($($t:ty),+) => { $( impl Primitive for $t { fn fmt(&self, buf: &mut String) { write!(buf, "{self}").ok(); } } )+ } } impl_primitive!(char, u32, u64, u128, usize, i32, i64, i128, f32, f64, &str, &String, String); impl Primitive for u8 { fn fmt(&self, buf: &mut String) { buf.push(*self as char); } } impl Primitive for bool { fn fmt(&self, buf: &mut String) { *buf += if *self { "Yes" } else { "No" }; } } } pub mod traits { pub trait Grid: Copy + Default { const AROUND: [[i64; 2]; 8] = [[0, -1], [0, 1], [-1, 0], [1, 0], [-1, -1], [-1, 1], [1, -1], [1, 1]]; fn add(self, rhs: [i64; 2]) -> Self; fn add_char(self, c: char, n: i64) -> Self { let mut d = Self::AROUND[match c { 'L' => 0, 'R' => 1, 'U' => 2, 'D' => 3, _ => unreachable!() }]; d[0] *= n; d[1] *= n; self.add(d) } fn around4(self) -> [Self; 4] { let mut res = [Default::default(); 4]; for i in 0..4 { res[i] = self.add(Self::AROUND[i]); } res } fn around8(self) -> [Self; 8] { let mut res = [Default::default(); 8]; for i in 0..8 { res[i] = self.add(Self::AROUND[i]); } res } fn rotate(self, n: usize, t: i64) -> Self; } impl Grid for [usize; 2] { fn add(mut self, rhs: [i64; 2]) -> Self { for i in 0..2 { self[i] = self[i].wrapping_add_signed(rhs[i] as isize); } self } fn rotate(self, n: usize, t: i64) -> Self { let [i, j] = self; match t.rem_euclid(4) { 0 => [i, j], 1 => [j, n-1-i], 2 => [n-1-i, n-1-j], 3 => [n-1-j, i], _ => unreachable!() } } } impl Grid for [i64; 2] { fn add(mut self, rhs: [i64; 2]) -> Self { for i in 0..2 { self[i] += rhs[i]; } self } fn rotate(self, _: usize, _: i64) -> Self { unimplemented!() } } pub trait CharUtil: Clone { const LOWER: [Self; 26]; const UPPER: [Self; 26]; const NUMBER: [Self; 10]; fn parse_lower(self) -> usize; fn parse_upper(self) -> usize; fn parse_digit(self) -> usize; fn flip(self) -> Self; } impl CharUtil for char { const LOWER: [char; 26] = { let (mut out, mut i) = (['_'; 26], 0); while i < 26 { out[i] = (i+97) as u8 as char; i += 1; } out }; const UPPER: [char; 26] = { let (mut out, mut i) = (['_'; 26], 0); while i < 26 { out[i] = (i+65) as u8 as char; i += 1; } out }; const NUMBER: [char; 10] = { let (mut res, mut i) = (['_'; 10], 0); while i < 10 { res[i] = (i+48) as u8 as char; i += 1; } res }; fn parse_lower(self) -> usize { debug_assert!('a' <= self && self <= 'z'); self as usize - 97 } fn parse_upper(self) -> usize { debug_assert!('A' <= self && self <= 'Z'); self as usize - 65 } fn parse_digit(self) -> usize { debug_assert!('0' <= self && self <= '9'); self as usize - 48 } fn flip(self) -> Self { (self as u8 ^ 32) as char } } use std::collections::{BTreeMap, HashMap}; use std::hash::Hash; pub trait MapInit { type K; type V; fn init(&mut self, key: Self::K, init: Self::V) -> &mut Self::V; fn init_with(&mut self, key: Self::K, init: impl FnOnce() -> Self::V) -> &mut Self::V; } impl<K: Eq + Hash, V> MapInit for HashMap<K, V> { type K = K; type V = V; fn init(&mut self, key: K, init: V) -> &mut V { self.entry(key).or_insert(init) } fn init_with(&mut self, key: K, init: impl FnOnce() -> Self::V) -> &mut V { self.entry(key).or_insert_with(init) } } impl<K: Ord, V> MapInit for BTreeMap<K, V> { type K = K; type V = V; fn init(&mut self, key: K, init: V) -> &mut V { self.entry(key).or_insert(init) } fn init_with(&mut self, key: Self::K, init: impl FnOnce() -> Self::V) -> &mut Self::V { self.entry(key).or_insert_with(init) } } } pub mod macros { #[macro_export] macro_rules! nest { [void; $n:expr] => { std::vec![std::vec![]; $n] }; [void; $n:expr $(;$m:expr)+] => { std::vec![crate::nest![void$(;$m)+]; $n] }; [$($v:expr),*] => { std::vec![$($v),*] }; [$e:expr; $n:expr] => { std::vec![$e; $n] }; [$e:expr; $n:expr $(;$m:expr)+] => { std::vec![crate::nest![$e$(;$m)+]; $n] }; } #[macro_export] macro_rules! min { ($($vl:expr),+) => { [$($vl),+].into_iter().reduce(|x,y| if x <= y {x} else {y}).unwrap() } } #[macro_export] macro_rules! max { ($($vl:expr),+) => { [$($vl),+].into_iter().reduce(|x,y| if x >= y {x} else {y}).unwrap() } } #[macro_export] macro_rules! chmin { ($dst:expr; $v:expr) => { { let v = $v; if v < $dst { $dst = v; true } else { false } } }; ($dst:expr; $($vl:expr),+) => { crate::chmin!($dst; crate::min!($($vl),+)) } } #[macro_export] macro_rules! chmax { ($dst:expr; $v:expr) => { { let v = $v; if $dst < v { $dst = v; true } else { false } } }; ($dst:expr; $($vl:expr),+) => { crate::chmax!($dst; crate::max!($($vl),+)) } } } pub mod func { use std::ops::{RangeBounds, Bound}; pub fn binary_search(low: usize, high: usize) -> Option<usize> { if 1 < high.wrapping_sub(low) { Some(low.wrapping_add(high)/2) } else { None } } pub fn to_bounds(range: impl RangeBounds<usize>, sup: usize) -> [usize; 2] { let mut l = match range.start_bound() { Bound::Included(&v) => v, Bound::Excluded(&v) => v+1, Bound::Unbounded => 0 }; let mut r = match range.end_bound() { Bound::Included(&v) => v+1, Bound::Excluded(&v) => v, Bound::Unbounded => sup }; if l >= r { l = 0; r = 0; } assert!(r <= sup, "valid: 0..{sup}, input: {l}..{r}"); [l, r] } pub(crate) fn join(s: impl Iterator<Item = String>) -> Option<String> { let mut res = s.into_iter().fold(String::new(), |mut acc, e| { acc += &e; acc += ", "; acc }); if res.is_empty() { return None; } res.truncate(res.len() - 2); Some(res) } } } }
Solalyth