From c5167b08fadadddecd8523c23d94add230bc60fd Mon Sep 17 00:00:00 2001 From: bouzuya Date: Thu, 20 Jul 2023 21:05:14 +0900 Subject: [PATCH] arc114 a, b --- cargo-atcoder/contests/arc114/Cargo.lock | 16 +- cargo-atcoder/contests/arc114/Cargo.toml | 4 +- cargo-atcoder/contests/arc114/src/bin/a.rs | 47 +++-- cargo-atcoder/contests/arc114/src/bin/b.rs | 189 ++++++++++----------- 4 files changed, 135 insertions(+), 121 deletions(-) diff --git a/cargo-atcoder/contests/arc114/Cargo.lock b/cargo-atcoder/contests/arc114/Cargo.lock index 14b0518f..ce23c4b1 100644 --- a/cargo-atcoder/contests/arc114/Cargo.lock +++ b/cargo-atcoder/contests/arc114/Cargo.lock @@ -11,9 +11,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "lazy_static" @@ -58,9 +58,9 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ "autocfg", "num-traits", @@ -68,9 +68,9 @@ dependencies = [ [[package]] name = "num-iter" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" dependencies = [ "autocfg", "num-integer", @@ -91,9 +91,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", ] diff --git a/cargo-atcoder/contests/arc114/Cargo.toml b/cargo-atcoder/contests/arc114/Cargo.toml index 2fae1302..f0e9d18b 100644 --- a/cargo-atcoder/contests/arc114/Cargo.toml +++ b/cargo-atcoder/contests/arc114/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "arc114" version = "0.1.0" -authors = ["bouzuya "] edition = "2018" # dependencies added to new project @@ -10,3 +9,6 @@ num = "=0.2.1" proconio = { version = "=0.3.6", features = ["derive"] } superslice = "=1.0.0" +[profile.release] +lto = true +panic = 'abort' diff --git a/cargo-atcoder/contests/arc114/src/bin/a.rs b/cargo-atcoder/contests/arc114/src/bin/a.rs index 69b36513..3e31e1f1 100644 --- a/cargo-atcoder/contests/arc114/src/bin/a.rs +++ b/cargo-atcoder/contests/arc114/src/bin/a.rs @@ -1,36 +1,49 @@ -use std::cmp; - use proconio::input; +fn sieve_of_eratosthenes(n: usize) -> Vec { + let mut p = vec![]; + let mut b = vec![true; n + 1]; + for i in 2.. { + if i * i > n { + for j in i..=n { + if b[j] { + p.push(j); + } + } + break; + } + if b[i] { + p.push(i); + for j in (i + i..=n).step_by(i) { + b[j] = false; + } + } + } + p +} + fn main() { input! { n: usize, x: [usize; n], }; - let mut ps = vec![]; - for x in 2..=50 { - if ps.iter().all(|p_i| x % p_i != 0) { - ps.push(x); - } - } + let ps = sieve_of_eratosthenes(50); assert_eq!(ps.len(), 15); - let mut ans = ps.iter().product::(); + let mut ans = ps.iter().copied().product::(); for bits in 0..1 << ps.len() { - let mut qs = vec![]; - for i in 0..ps.len() { - if (bits >> i) & 1 == 1 { - qs.push(ps[i]); - } - } - + let qs = (0..ps.len()) + .filter(|i| ((bits >> i) & 1) == 1) + .map(|i| ps[i]) + .collect::>(); if x.iter() .copied() .all(|x_i| qs.iter().copied().any(|q_i| x_i % q_i == 0)) { - ans = cmp::min(ans, qs.iter().product::()); + ans = ans.min(qs.iter().copied().product::()); } } + println!("{}", ans); } diff --git a/cargo-atcoder/contests/arc114/src/bin/b.rs b/cargo-atcoder/contests/arc114/src/bin/b.rs index 59f30a28..69a68ce2 100644 --- a/cargo-atcoder/contests/arc114/src/bin/b.rs +++ b/cargo-atcoder/contests/arc114/src/bin/b.rs @@ -10,7 +10,6 @@ fn main() { let mut dsu = Dsu::new(n); for (i, f_i) in f.iter().copied().enumerate() { dsu.merge(i, f_i); - dsu.merge(f_i, f[f_i]); } let ans = ModInt::new(2).pow(dsu.groups().len() as u64) - ModInt::new(1); println!("{}", ans); @@ -18,6 +17,100 @@ fn main() { //https://github.com/rust-lang-ja/ac-library-rs +pub mod dsu { + /// Implement (union by size) + (path compression) + /// Reference: + /// Zvi Galil and Giuseppe F. Italiano, + /// Data structures and algorithms for disjoint set union problems + 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::>>() + } + } + + #[cfg(test)] + mod tests { + use super::*; + + #[test] + fn dsu_works() { + let mut d = Dsu::new(4); + d.merge(0, 1); + assert_eq!(d.same(0, 1), true); + d.merge(1, 2); + assert_eq!(d.same(0, 2), true); + assert_eq!(d.size(0), 3); + assert_eq!(d.same(0, 3), false); + assert_eq!(d.groups(), vec![vec![0, 1, 2], vec![3]]); + } + } +} + +//https://github.com/rust-lang-ja/ac-library-rs + pub mod internal_math { // remove this after dependencies has been added #![allow(dead_code)] @@ -1641,97 +1734,3 @@ pub mod modint { } } } - -//https://github.com/rust-lang-ja/ac-library-rs - -pub mod dsu { - /// Implement (union by size) + (path compression) - /// Reference: - /// Zvi Galil and Giuseppe F. Italiano, - /// Data structures and algorithms for disjoint set union problems - 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::>>() - } - } - - #[cfg(test)] - mod tests { - use super::*; - - #[test] - fn dsu_works() { - let mut d = Dsu::new(4); - d.merge(0, 1); - assert_eq!(d.same(0, 1), true); - d.merge(1, 2); - assert_eq!(d.same(0, 2), true); - assert_eq!(d.size(0), 3); - assert_eq!(d.same(0, 3), false); - assert_eq!(d.groups(), vec![vec![0, 1, 2], vec![3]]); - } - } -}