#![allow(unused_imports)] use proconio::{input_interactive, marker::*}; use itertools::*; fn wait() -> (usize, usize) { input_interactive!{ s: Chars, v: usize, k: usize } assert_eq!(s, "COUNT".chars().collect_vec()); (v, k) } fn wait_guess() { input_interactive!{ _: Chars, _: usize, _: usize } } fn ask(i: usize) -> (usize, usize) { println!("ASK {}", i); input_interactive!{ s: Chars, v: usize, k: usize } assert_eq!(s, "COUNT".chars().collect_vec()); (v, k) } fn enumerate(n_hands: usize, val_min: u8, rem: usize, val_max: u8, acc: &mut Vec, results: &mut Vec>) { if acc.len() == n_hands { results.push(acc.clone()); } else if val_min <= val_max { acc.push(val_min); if rem == 1 { enumerate(n_hands, val_min + 1, val_min as usize + 1, val_max, acc, results); } else { enumerate(n_hands, val_min, rem - 1, val_max, acc, results); } acc.pop(); for i in val_min + 1..=val_max { acc.push(i); enumerate(n_hands, i, i as usize - 1, val_max, acc, results); acc.pop(); } } } fn main() { input_interactive!{ id: usize, n_hands: usize, val_max: u8, ns: [u8; n_hands], } let mut results = vec![]; enumerate(n_hands, 1, 1, val_max, &mut vec![], &mut results); eprintln!("{}", results.len()); for (a, b) in results.iter().tuple_windows() { assert!(a < b); } let p = results.binary_search(&ns).unwrap(); let repr = { let mut nums = vec![]; let mut p = p; let mut n = results.len(); while n > 0 { nums.push(p % val_max as usize); p /= val_max as usize; n /= val_max as usize; } assert_eq!(p, 0); nums }; eprintln!("pos = {p}, repr = {repr:?}"); let mut other_repr = vec![]; let mut counts = vec![None; val_max as usize]; for i in 0..repr.len() * 2 { input_interactive!{ s: String } if s == "WAIT" { let (v, k) = wait(); other_repr.push(v - 1); if counts[v - 1].is_none() { counts[v - 1] = Some(k); } else { assert_eq!(counts[v - 1], Some(k)); } } else { assert_eq!(s, "TURN"); let v = repr[i / 2]; let (_, k) = ask(v + 1); if counts[v].is_none() { counts[v] = Some(k); } else { assert_eq!(counts[v], Some(k)); } } } let other_ns = { let mut idx = 0; let mut p = 1; for a in other_repr { idx += p * a; p *= val_max as usize; } results[idx].clone() }; dbg!(other_ns.clone()); let more_queries = (0..val_max as usize) .filter(|&i| counts[i].is_none()) .map(|i| i + 1) .collect_vec(); dbg!(more_queries.clone()); for v in more_queries { input_interactive!{ s: String } if s == "WAIT" { let (v1, k) = wait(); assert_eq!(v, v1); assert!(counts[v - 1].is_none()); counts[v - 1] = Some(k); } else { assert_eq!(s, "TURN"); let (_, k) = ask(v); assert!(counts[v - 1].is_none()); counts[v - 1] = Some(k); } } for v in ns { if let Some(k) = counts[v as usize - 1].as_mut() { *k -= 1 } } for v in other_ns { if let Some(k) = counts[v as usize - 1].as_mut() { *k -= 1 } } let mut ans = vec![]; for i in 1..=val_max { if let Some(k) = counts[i as usize - 1] { ans.extend(std::iter::repeat(i).take(k)); } } { input_interactive!{ s: String } if s == "WAIT" { wait_guess(); input_interactive!{ s: String } assert_eq!(s, "TURN"); } dbg!(ans.clone()); println!("GUESS {}", ans.iter().join(" ")); input_interactive!{ s: String, p: usize, ok: u8 } assert_eq!(p, id); eprintln!("got {s}, {ok}"); } loop { input_interactive!{ s: String } if s == "END" { input_interactive!{ q: usize } eprintln!("{q} queries"); } else { assert_eq!(s, "WAIT"); } } }