// -*- coding: utf-8-unix -*- #![allow(dead_code, unused_imports, unused_macros, unused_variables)] use std::cmp::{max, min, Ordering, Reverse}; use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque}; use std::fmt::Debug; use std::io::{self, Read}; use std::str::FromStr; const INF_I32: i32 = 1_i32 << 30; const INF_I64: i64 = 1_i64 << 60; const INF_I128: i128 = 1_i128 << 120; const INF_USIZE: usize = usize::MAX / 4; const INF: i64 = INF_I64; const UINF: usize = INF_USIZE; const INF128: i128 = INF_I128; const MOD1: i64 = 1_000_000_007; const MOD9: i64 = 998_244_353; const MOD: i64 = MOD9; const UMOD: usize = MOD as usize; // ============================================================================= // Input // ========================================================================= #[allow(dead_code)] fn read() -> T { let mut s = String::new(); std::io::stdin().read_line(&mut s).ok(); s.trim().parse().ok().unwrap() } #[allow(dead_code)] fn read_vec() -> Vec { read::() .split_whitespace() .map(|e| e.parse().ok().unwrap()) .collect() } #[allow(dead_code)] fn read_mat(n: usize) -> Vec> { (0..n).map(|_| read_vec()).collect() } macro_rules! uin { ($($x:ident),+ $(,)?) => { let values = read_vec::(); let mut iter = values.into_iter(); $( let mut $x = iter .next() .expect("入力の要素数が不足しています"); )+ }; } macro_rules! iin { ($($x:ident),+ $(,)?) => { let values = read_vec::(); let mut iter = values.into_iter(); $( let mut $x = iter .next() .expect("入力の要素数が不足しています"); )+ }; } macro_rules! cin { ($x:ident $(,)?) => { let mut $x: Vec = read::().chars().collect(); }; } macro_rules! inuv { ($x:ident $(,)?) => { let mut $x = read_vec::(); }; } macro_rules! iniv { ($x:ident $(,)?) => { let mut $x = read_vec::(); }; } // ============================================================================= // Output / Debug // ============================================================================= macro_rules! p { () => { println!(); }; ($value:expr $(,)?) => { println!("{}", $value); }; ($fmt:literal, $($arg:tt)*) => { println!($fmt, $($arg)*); }; } macro_rules! join { ($iter:expr, $separator:expr $(,)?) => { ($iter) .into_iter() .map(|x| x.to_string()) .collect::>() .join($separator) }; } macro_rules! pv { ($iter:expr $(,)?) => { println!("{}", join!($iter, " ")); }; ($iter:expr, $separator:expr $(,)?) => { println!("{}", join!($iter, $separator)); }; } macro_rules! yesno { ($condition:expr $(,)?) => { println!("{}", if $condition { "Yes" } else { "No" }); }; ($condition:expr, $yes:expr, $no:expr $(,)?) => { println!("{}", if $condition { $yes } else { $no }); }; } macro_rules! d { ($($value:expr),+ $(,)?) => { #[cfg(debug_assertions)] { eprint!("[{}:{}]", file!(), line!()); $( eprint!(" {} = {:?}", stringify!($value), &$value); )+ eprintln!(); } }; } // ============================================================================= // Scalar / Vec utilities // ============================================================================= macro_rules! chmin { ($base:expr, $($value:expr),+ $(,)?) => {{ let mut updated = false; $( let value = $value; if $base > value { $base = value; updated = true; } )+ updated }}; } macro_rules! chmax { ($base:expr, $($value:expr),+ $(,)?) => {{ let mut updated = false; $( let value = $value; if $base < value { $base = value; updated = true; } )+ updated }}; } macro_rules! min { // collection: Vec、配列、スライスなど ($iter:expr $(,)?) => {{ ($iter) .iter() .min() .cloned() .expect("min! called on an empty iterator") }}; // 複数の値 ($first:expr, $($rest:expr),+ $(,)?) => {{ let mut answer = ($first).clone(); $( chmin!(answer, ($rest).clone()); )+ answer }}; } macro_rules! max { // collection: Vec、配列、スライスなど ($iter:expr $(,)?) => {{ ($iter) .iter() .max() .cloned() .expect("max! called on an empty iterator") }}; // 複数の値 ($first:expr, $($rest:expr),+ $(,)?) => {{ let mut answer = ($first).clone(); $( chmax!(answer, ($rest).clone()); )+ answer }}; } macro_rules! ndvec { ($value:expr; $len:expr) => { vec![$value; $len] }; ($value:expr; $len:expr, $($rest:expr),+ $(,)?) => { vec![ndvec![$value; $($rest),+]; $len] }; } macro_rules! prefix_sum { ($values:expr $(,)?) => {{ let values = &$values; let mut prefix = Vec::with_capacity(values.len() + 1); prefix.push(Default::default()); for &value in values.iter() { let next = prefix.last().copied().unwrap() + value; prefix.push(next); } prefix }}; } // 数学的な floor(a / b)。b != 0。 macro_rules! div_floor { ($a:expr, $b:expr $(,)?) => {{ let a = $a; let b = $b; let q = a / b; let r = a % b; if r != 0 && ((r > 0) != (b > 0)) { q - 1 } else { q } }}; } // 数学的な ceil(a / b)。b != 0。 macro_rules! div_ceil { ($a:expr, $b:expr $(,)?) => {{ let a = $a; let b = $b; let q = a / b; let r = a % b; if r != 0 && ((r > 0) == (b > 0)) { q + 1 } else { q } }}; } // ============================================================================= // Integer / floating-point binary search // ============================================================================= // pred(ok) == true, pred(ng) == false を保ち、最後に true 側の境界を返す。 // ok < ng と ok > ng の双方に対応する。 macro_rules! binsearch { (ok = $ok:expr, ng = $ng:expr, $pred:expr $(,)?) => {{ let mut ok = $ok; let mut ng = $ng; let mut pred = $pred; while ok.abs_diff(ng) > 1 { let mid = if ok < ng { ok + (ng - ok) / 2 } else { ng + (ok - ng) / 2 }; if pred(mid) { ok = mid; } else { ng = mid; } } ok }}; } // false ... true の単調列に対し、最初の true を返す。 // ng は false 側の番兵、ok は true 側の番兵。 macro_rules! first_true { ($ng:expr, $ok:expr, $pred:expr $(,)?) => { binsearch!(ok = $ok, ng = $ng, $pred) }; } // true ... false の単調列に対し、最後の true を返す。 // ok は true 側の番兵、ng は false 側の番兵。 macro_rules! last_true { ($ok:expr, $ng:expr, $pred:expr $(,)?) => { binsearch!(ok = $ok, ng = $ng, $pred) }; } // 浮動小数点版。回数を明示することで停止条件の曖昧さを避ける。 macro_rules! binsearch_f64 { (ok = $ok:expr, ng = $ng:expr, iter = $iter:expr, $pred:expr $(,)?) => {{ let mut ok = $ok; let mut ng = $ng; let mut pred = $pred; for _ in 0..$iter { let mid = (ok + ng) * 0.5; if pred(mid) { ok = mid; } else { ng = mid; } } ok }}; } // ============================================================================= // Sorted slice bounds // ============================================================================= macro_rules! lower_bound { ($slice:expr, $value:expr $(,)?) => {{ let value = $value; ($slice).partition_point(|x| x < &value) }}; } macro_rules! upper_bound { ($slice:expr, $value:expr $(,)?) => {{ let value = $value; ($slice).partition_point(|x| x <= &value) }}; } // UTIL macro_rules! neighbors4 { ($y:expr, $x:expr, $h:expr, $w:expr $(,)?) => {{ const DY: [isize; 4] = [-1, 0, 1, 0]; const DX: [isize; 4] = [0, 1, 0, -1]; (0..4).filter_map(move |dir| { let ny = $y as isize + DY[dir]; let nx = $x as isize + DX[dir]; if 0 <= ny && ny < $h as isize && 0 <= nx && nx < $w as isize { Some((ny as usize, nx as usize)) } else { None } }) }}; } macro_rules! run_length { ($iter:expr $(,)?) => {{ let mut result = Vec::new(); for value in $iter { match result.last_mut() { Some((last, count)) if *last == value => { *count += 1usize; } _ => { result.push((value, 1usize)); } } } result }}; } macro_rules! vector_compress { ($iter:expr $(,)?) => {{ let values: Vec<_> = ($iter).into_iter().collect(); let mut coordinates = values.clone(); coordinates.sort(); coordinates.dedup(); let compressed = values .iter() .map(|value| coordinates.binary_search(value).unwrap()) .collect::>(); (compressed, coordinates) }}; } // ============================================================================= // Map / Set literals and counters // ============================================================================= macro_rules! map { ($($key:expr => $value:expr),* $(,)?) => {{ let mut map = ::std::collections::BTreeMap::new(); $(map.insert($key, $value);)* map }}; } macro_rules! set { ($($value:expr),* $(,)?) => {{ let mut set = ::std::collections::BTreeSet::new(); $(set.insert($value);)* set }}; } macro_rules! count_map { ($iter:expr $(,)?) => {{ let mut count = BTreeMap::new(); for value in $iter { *count.entry(value).or_insert(0usize) += 1; } count }}; } macro_rules! map_add { ($map:expr, $key:expr, $delta:expr $(,)?) => {{ let key = $key; let delta = $delta; let map = &mut $map; *map.entry(key).or_insert(0) += delta; }}; } macro_rules! map_inc { ($map:expr, $key:expr $(,)?) => { map_add!($map, $key, 1) }; } macro_rules! map_sub { ($map:expr, $key:expr, $delta:expr $(,)?) => {{ let key = $key; let delta = $delta; let map = &mut $map; let remove = match map.get_mut(&key) { Some(value) => { if *value <= delta { true } else { *value -= delta; false } } None => false, }; if remove { map.remove(&key); true } else { false } }}; } macro_rules! map_dec { ($map:expr, $key:expr $(,)?) => { map_sub!($map, $key, 1) }; } macro_rules! sum { ($iter:expr $(,)?) => {{ let mut sum = 0; for &value in ($iter).iter() { sum += value; } sum }}; } pub struct Dsu { n: usize, // root node: -1 * component size // otherwise: parent parent_or_size: Vec, } impl Dsu { // 0 <= size <= 10^8 is constrained. pub fn new(size: usize) -> Self { Self { n: size, parent_or_size: vec![-1; size], } } pub fn merge(&mut self, a: usize, b: usize) -> usize { assert!(a < self.n); assert!(b < self.n); let (mut x, mut y) = (self.leader(a), self.leader(b)); if x == y { return x; } if -self.parent_or_size[x] < -self.parent_or_size[y] { std::mem::swap(&mut x, &mut y); } self.parent_or_size[x] += self.parent_or_size[y]; self.parent_or_size[y] = x as i32; x } pub fn same(&mut self, a: usize, b: usize) -> bool { assert!(a < self.n); assert!(b < self.n); self.leader(a) == self.leader(b) } pub fn leader(&mut self, a: usize) -> usize { assert!(a < self.n); if self.parent_or_size[a] < 0 { return a; } self.parent_or_size[a] = self.leader(self.parent_or_size[a] as usize) as i32; self.parent_or_size[a] as usize } pub fn size(&mut self, a: usize) -> usize { assert!(a < self.n); let x = self.leader(a); -self.parent_or_size[x] as usize } pub fn groups(&mut self) -> Vec> { let mut leader_buf = vec![0; self.n]; let mut group_size = vec![0; self.n]; for i in 0..self.n { leader_buf[i] = self.leader(i); group_size[leader_buf[i]] += 1; } let mut result = vec![Vec::new(); self.n]; for i in 0..self.n { result[i].reserve(group_size[i]); } for i in 0..self.n { result[leader_buf[i]].push(i); } result .into_iter() .filter(|x| !x.is_empty()) .collect::>>() } } const TRUE: &bool = &true; const FALSE: &bool = &false; #[derive(Clone, Debug)] /// Efficient bool collection pub struct BitSet { buf: Vec, size: usize, } impl BitSet { #[allow(dead_code)] pub fn new(size: usize) -> BitSet { BitSet { buf: vec![0; (size + 63) / 64], size, } } #[allow(dead_code)] pub fn set(&mut self, i: usize, b: bool) { assert!(i < self.size); if b { self.buf[i >> 6] |= 1 << (i & 63); } else { self.buf[i >> 6] &= !(1 << (i & 63)); } } #[allow(dead_code)] pub fn count_ones(&self) -> u32 { self.buf.iter().map(|x| x.count_ones()).sum() } #[allow(dead_code)] fn chomp(&mut self) { let r = self.size & 63; if r != 0 { if let Some(x) = self.buf.last_mut() { let d = 64 - r; *x = (*x << d) >> d; } } } } impl std::ops::Index for BitSet { type Output = bool; fn index(&self, index: usize) -> &bool { [FALSE, TRUE][(self.buf[index >> 6] >> (index & 63)) as usize & 1] } } #[allow(clippy::suspicious_op_assign_impl)] impl std::ops::ShlAssign for BitSet { fn shl_assign(&mut self, x: usize) { let q = x >> 6; let r = x & 63; if q >= self.buf.len() { for x in &mut self.buf { *x = 0; } return; } if r == 0 { for i in (q..self.buf.len()).rev() { self.buf[i] = self.buf[i - q]; } } else { for i in (q + 1..self.buf.len()).rev() { self.buf[i] = (self.buf[i - q] << r) | (self.buf[i - q - 1] >> (64 - r)); } self.buf[q] = self.buf[0] << r; } for x in &mut self.buf[..q] { *x = 0; } self.chomp(); } } impl std::ops::Shl for BitSet { type Output = Self; fn shl(mut self, x: usize) -> Self { self <<= x; self } } #[allow(clippy::suspicious_op_assign_impl)] impl std::ops::ShrAssign for BitSet { fn shr_assign(&mut self, x: usize) { let q = x >> 6; let r = x & 63; if q >= self.buf.len() { for x in &mut self.buf { *x = 0; } return; } if r == 0 { for i in 0..self.buf.len() - q { self.buf[i] = self.buf[i + q]; } } else { for i in 0..self.buf.len() - q - 1 { self.buf[i] = (self.buf[i + q] >> r) | (self.buf[i + q + 1] << (64 - r)); } let len = self.buf.len(); self.buf[len - q - 1] = self.buf[len - 1] >> r; } let len = self.buf.len(); for x in &mut self.buf[len - q..] { *x = 0; } } } impl std::ops::Shr for BitSet { type Output = Self; fn shr(mut self, x: usize) -> Self { self >>= x; self } } impl<'a> std::ops::BitAndAssign<&'a BitSet> for BitSet { fn bitand_assign(&mut self, rhs: &'a Self) { for (a, b) in self.buf.iter_mut().zip(rhs.buf.iter()) { *a &= *b; } } } impl<'a> std::ops::BitAnd<&'a BitSet> for BitSet { type Output = Self; fn bitand(mut self, rhs: &'a Self) -> Self { self &= rhs; self } } impl<'a> std::ops::BitOrAssign<&'a BitSet> for BitSet { fn bitor_assign(&mut self, rhs: &'a Self) { for (a, b) in self.buf.iter_mut().zip(rhs.buf.iter()) { *a |= *b; } self.chomp(); } } impl<'a> std::ops::BitOr<&'a BitSet> for BitSet { type Output = Self; fn bitor(mut self, rhs: &'a Self) -> Self { self |= rhs; self } } impl<'a> std::ops::BitXorAssign<&'a BitSet> for BitSet { fn bitxor_assign(&mut self, rhs: &'a Self) { for (a, b) in self.buf.iter_mut().zip(rhs.buf.iter()) { *a ^= *b; } self.chomp(); } } impl<'a> std::ops::BitXor<&'a BitSet> for BitSet { type Output = Self; fn bitxor(mut self, rhs: &'a Self) -> Self { self ^= rhs; self } } fn main() { uin!(t); for _ in 0..t { uin!(n, s); inuv!(a); let mut dp = BitSet::new(s + 1); dp.set(0, true); for x in a { if x > s { continue; } let shifted = dp.clone() << x; dp |= &shifted; } let mut ans = 0; for x in (0..=s).rev() { if dp[x] { ans = x; break; } } println!("{}", ans); } }