//{{{ #[allow(unused_macros)] macro_rules! getl { ( $( $t:ty ),* ) => { { let mut s = String::new(); std::io::stdin().read_line(&mut s).unwrap(); let s = s.trim_right(); let mut ws = s.split_whitespace(); ($(ws.next().unwrap().parse::<$t>().unwrap()),*) } }; } #[allow(unused_macros)] macro_rules! getl_vec { ( $t:ty ) => {{ let mut s = String::new(); std::io::stdin().read_line(&mut s).unwrap(); let s = s.trim_right(); s.split_whitespace() .map(|x| x.parse().unwrap()) .collect::>() }}; } //}}} // \sum_i \sum_j a_i % a_j // \sum_i ai % d = s // s === (\sum_i a_i) % d // s - (\sum_i a_i) % d は? // 各a_iに対して floor(a_i / d) * d だけ差が出る // m * d <= a_i < (m + 1) * d となるような個数cを求めて c * m * d // O(log(n)^2 * n) fn main() { let n = getl!(usize); let mut a = getl_vec!(i64); a.sort(); let s: i64 = a.iter().sum(); let mut ans: i64 = 0; for a_i in a.iter().copied() { let mut now = s; let d = a_i; let mut l: Option = Some(0); let mut r = None; let mut m = 0; loop { r = a.binary_search_left(|a_i| *a_i >= (m + 1) * d); // dbg!(m, l, r); if l.is_none() { break; } match (l, r) { (Some(l), Some(r)) => { now -= (r as i64 - l as i64) * m * d; } (None, Some(r)) => { now -= (r as i64) * m * d; } (Some(l), None) => { now -= (n as i64 - l as i64) * m * d; }, (None, None) => {}, } l = r; m += 1; } ans += now; // dbg!(a_i, ans, now); } println!("{}", ans); } trait BinarySearch { fn binary_search_right(&self, condition: F) -> Option; fn binary_search_left(&self, condition: F) -> Option; } impl BinarySearch for Vec where F: Fn(&T) -> bool, { fn binary_search_right(&self, condition: F) -> Option { if self.is_empty() { return None; } let len = self.len(); if condition(&self[len - 1]) { return Some(len - 1); } if !condition(&self[0]) { return None; } let mut left = 0; let mut right = len - 1; while left + 1 < right { let mid = (left + right) / 2; if condition(&self[mid]) { left = mid; } else { right = mid; } } Some(left) } fn binary_search_left(&self, condition: F) -> Option { if self.is_empty() { return None; } let len = self.len(); if condition(&self[0]) { return Some(0); } if !condition(&self[len - 1]) { return None; } let mut left = 0; let mut right = len - 1; while left + 1 < right { let mid = (left + right) / 2; if condition(&self[mid]) { right = mid; } else { left = mid; } } Some(right) } }