https://atcoder.jp/contests/abc403/tasks/abc403_d
Dで割った余りで分類してソートします。同じ値ならカウントします。入力例1だと余り1の方は、
(1, 2), (3, 1), (5, 1)
DPで削除する個数を最小にするようにします。
D=0の場合は重複を削除するだけです。
// Forbidden Difference #![allow(non_snake_case)] //////////////////// library //////////////////// fn read<T: std::str::FromStr>() -> T { let mut line = String::new(); std::io::stdin().read_line(&mut line).ok(); line.trim().parse().ok().unwrap() } fn read_vec<T: std::str::FromStr>() -> Vec<T> { read::<String>().split_whitespace() .map(|e| e.parse().ok().unwrap()).collect() } //////////////////// process //////////////////// fn read_input() -> (i32, Vec<i32>) { let v: Vec<i32> = read_vec(); let D = v[1]; let A: Vec<i32> = read_vec(); (D, A) } fn convert(mut rs: Vec<i32>) -> Vec<(i32, usize)> { rs.sort(); let mut v: Vec<(i32, usize)> = vec![]; let mut prev: i32 = -1; let mut num: usize = 0; for a in rs.into_iter() { if prev == -1 { num = 1 } else if a != prev { v.push((prev, num)); num = 1 } else { num += 1 } prev = a; } v.push((prev, num)); v } use std::cmp::min; fn count(D: i32, v: Vec<(i32, usize)>) -> usize { let mut prev = -D * 2; let mut dp: [usize; 2] = [0, 0]; // (使った, 使わない) for (a, n) in v.into_iter() { let m = min(dp[0], dp[1]); if a == prev + D { dp = [dp[1], m+n] } else { dp = [m, m+n] } prev = a } min(dp[0], dp[1]) } use std::collections::HashMap; fn F(D: i32, A: Vec<i32>) -> usize { if D == 0 { let N = A.len(); let mut c: HashMap<i32, usize> = HashMap::new(); for a in A.into_iter() { let e = c.entry(a).or_insert(0); *e += 1 } return N - c.len() } let mut rss: Vec<Vec<i32>> = vec![vec![]; D as usize]; for a in A.into_iter() { let r = a % D; rss[r as usize].push(a) } let mut counter: usize = 0; for rs in rss.into_iter() { if rs.is_empty() { continue } let v = convert(rs); counter += count(D, v) } counter } fn main() { let (D, A) = read_input(); println!("{}", F(D, A)) }