Skip to content

Commit

Permalink
arc114 a, b
Browse files Browse the repository at this point in the history
  • Loading branch information
bouzuya committed Jul 20, 2023
1 parent 23b4780 commit c5167b0
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 121 deletions.
16 changes: 8 additions & 8 deletions cargo-atcoder/contests/arc114/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion cargo-atcoder/contests/arc114/Cargo.toml
@@ -1,7 +1,6 @@
[package]
name = "arc114"
version = "0.1.0"
authors = ["bouzuya <m@bouzuya.net>"]
edition = "2018"

# dependencies added to new project
Expand All @@ -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'
47 changes: 30 additions & 17 deletions 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<usize> {
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::<usize>();
let mut ans = ps.iter().copied().product::<usize>();
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::<Vec<usize>>();
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::<usize>());
ans = ans.min(qs.iter().copied().product::<usize>());
}
}

println!("{}", ans);
}
189 changes: 94 additions & 95 deletions cargo-atcoder/contests/arc114/src/bin/b.rs
Expand Up @@ -10,14 +10,107 @@ 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);
}

//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<i32>,
}

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<Vec<usize>> {
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::<Vec<Vec<usize>>>()
}
}

#[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)]
Expand Down Expand Up @@ -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<i32>,
}

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<Vec<usize>> {
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::<Vec<Vec<usize>>>()
}
}

#[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]]);
}
}
}

0 comments on commit c5167b0

Please sign in to comment.