// Reference: https://github.com/matajupi/matajupilib_snippets //  ∧_∧ // (。・ﻌ・。)つ━☆・*。 // ⊂   ノ    ✧・゜+. //  しーJ   °。+ *´¨) //          .· ´¸.·´¨) ¸.·¨) //           (¸.·´ ✧(¸.·’*✧ #![allow(dead_code, unused_imports, unused_macros, unexpected_cfgs)] #[macro_use] mod matajupilib { use crate::*; // ============================================================================= // Macros // ============================================================================= macro_rules! chmin { ($a:expr, $b:expr) => { if $b < $a { $a = $b; true } else { false } }; } macro_rules! chmax { ($a:expr, $b:expr) => { if $b > $a { $a = $b; true } else { false } }; } macro_rules! r { ($num:expr, $den:expr) => { Rational64::new($num, $den) }; } /// Debug print macro (Only works in Debug builds; ignored in Release builds) macro_rules! d { ($($a:expr),* $(,)?) => { #[cfg(debug_assertions)] eprintln!(concat!($(stringify!($a), " = {:?}, "),*), $($a),*); }; } // ============================================================================= // Constants & Type Aliases // ============================================================================= pub const IINF: i64 = 4_000_000_000_000_000_000; pub const UINF: usize = 1_000_000_000; pub const DX4: [i64; 4] = [1, 0, -1, 0]; pub const DY4: [i64; 4] = [0, 1, 0, -1]; pub const DX8: [i64; 8] = [1, 1, 0, -1, -1, -1, 0, 1]; pub const DY8: [i64; 8] = [0, 1, 1, 1, 0, -1, -1, -1]; pub type MinHeap = BinaryHeap>; pub type MaxHeap = BinaryHeap; // ============================================================================= // Type Cast Traits // ============================================================================= macro_rules! define_cast_trait { ($trait_name:ident, $fn_name:ident, $target_type:ty, $($source_type:ty),*) => { pub trait $trait_name { fn $fn_name(self) -> $target_type; } $( impl $trait_name for $source_type { #[inline] fn $fn_name(self) -> $target_type { self as $target_type } } )* }; } define_cast_trait!( AsUsize, u, usize, i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize, char, f32, f64 ); define_cast_trait!( AsI64, i, i64, i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize, char, f32, f64 ); define_cast_trait!( AsF64, f, f64, i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize, f32, f64 ); define_cast_trait!( AsI128, l, i128, i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize, char, f32, f64 ); pub trait AsMint { fn m(self) -> Mint; } impl AsMint for T where T: Into, { #[inline] fn m(self) -> Mint { self.into() } } // ============================================================================= // Helper Traits // ============================================================================= pub trait Unwrapper { fn uw(self) -> T; fn uwor(self, default: T) -> T; fn uworelse(self, f: F) -> T where F: FnOnce() -> T; } impl Unwrapper for Option { #[inline] fn uw(self) -> T { self.expect("None value") } #[inline] fn uwor(self, default: T) -> T { self.unwrap_or(default) } #[inline] fn uworelse(self, f: F) -> T where F: FnOnce() -> T, { self.unwrap_or_else(f) } } impl Unwrapper for Result { #[inline] fn uw(self) -> T { self.expect("Err value") } #[inline] fn uwor(self, default: T) -> T { self.unwrap_or(default) } #[inline] fn uworelse(self, f: F) -> T where F: FnOnce() -> T, { self.unwrap_or_else(|_| f()) } } pub trait ShortNumOps: Sized { fn sadd(self, rhs: Self) -> Self; fn ssub(self, rhs: Self) -> Self; fn smul(self, rhs: Self) -> Self; fn oadd(self, rhs: Self) -> (Self, bool); fn osub(self, rhs: Self) -> (Self, bool); fn omul(self, rhs: Self) -> (Self, bool); } macro_rules! impl_short_num_ops { ($($t:ty),*) => { $( impl ShortNumOps for $t { #[inline] fn sadd(self, rhs: Self) -> Self { self.saturating_add(rhs) } #[inline] fn ssub(self, rhs: Self) -> Self { self.saturating_sub(rhs) } #[inline] fn smul(self, rhs: Self) -> Self { self.saturating_mul(rhs) } #[inline] fn oadd(self, rhs: Self) -> (Self, bool) { self.overflowing_add(rhs) } #[inline] fn osub(self, rhs: Self) -> (Self, bool) { self.overflowing_sub(rhs) } #[inline] fn omul(self, rhs: Self) -> (Self, bool) { self.overflowing_mul(rhs) } } )* }; } impl_short_num_ops!( i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize ); pub trait MapExt { fn orins(&mut self, key: K, default: V) -> &mut V; fn ordef(&mut self, key: K) -> &mut V where V: Default; fn orwith V>(&mut self, key: K, f: F) -> &mut V; } impl MapExt for HashMap { #[inline] fn orins(&mut self, key: K, default: V) -> &mut V { self.entry(key).or_insert(default) } #[inline] fn ordef(&mut self, key: K) -> &mut V where V: Default, { self.entry(key).or_default() } #[inline] fn orwith V>(&mut self, key: K, f: F) -> &mut V { self.entry(key).or_insert_with(f) } } impl MapExt for BTreeMap { #[inline] fn orins(&mut self, key: K, default: V) -> &mut V { self.entry(key).or_insert(default) } #[inline] fn ordef(&mut self, key: K) -> &mut V where V: Default, { self.entry(key).or_default() } #[inline] fn orwith V>(&mut self, key: K, f: F) -> &mut V { self.entry(key).or_insert_with(f) } } pub trait StrExt { fn cv(&self) -> Vec; } impl StrExt for str { #[inline] fn cv(&self) -> Vec { self.chars().collect() } } // ============================================================================= // Iterator Extensions // ============================================================================= pub trait IntoIterExt: IntoIterator + Sized { #[inline] fn iit(self) -> Self::IntoIter { self.into_iter() } #[inline] fn col>(self) -> B { self.into_iter().collect() } #[inline] fn colv(self) -> Vec { self.into_iter().collect() } } impl IntoIterExt for T {} pub trait IterExt { #[inline] fn it(&self) -> <&Self as IntoIterator>::IntoIter where for<'a> &'a Self: IntoIterator, { self.into_iter() } #[inline] fn itm(&mut self) -> <&mut Self as IntoIterator>::IntoIter where for<'a> &'a mut Self: IntoIterator, { self.into_iter() } } impl IterExt for T {} // ============================================================================= // Scanner // ============================================================================= use std::io::Read; pub struct Scanner { iter: std::vec::IntoIter, } impl Scanner { pub fn new() -> Self { let mut s = String::new(); std::io::stdin().read_to_string(&mut s).unwrap(); Self { iter: s.split_whitespace().map(|s| s.to_string()) .collect::>().into_iter(), } } pub fn n(&mut self) -> T { self.iter.next().unwrap().parse().ok().unwrap() } pub fn ns(&mut self, n: usize) -> Vec { (0..n).map(|_| self.n()).collect() } } } // ============================================================================= // Imports & Main // ============================================================================= // AtCoder // use amplify::*; // use omniswap::swap; // use ordered_float::OrderedFloat as OF; // use rand::Rng; // use superslice::Ext; // yukicoder use ::num::{integer::*, rational::*, *}; use itertools::Itertools; use ac_library::*; use proconio::{marker::*, *}; // Other use std::cmp::{Reverse as R, *}; use std::collections::{HashMap as Map, HashSet as Set, *}; use std::f64::consts::*; use std::hash::{BuildHasher, Hash}; use std::mem::*; use std::ops::{Range, RangeBounds}; // AtCoder, yukicoder use ac_library::ModInt998244353 as Mint; // Other // type Mint = i64; use matajupilib::*; fn crt(a: &[i128], m: &[i128]) -> (i128, Vec) { assert!(a.len() == m.len()); let n = a.len(); let mut c = vec![0; n]; let mut m_prod = 1; let mut x = 0; for i in 0..n { let mut b = i128::extended_gcd(&m_prod, &-m[i]).x; b = (b + m[i]) % m[i]; c[i] = ((a[i] - x + m_prod * m[i]) % m[i]) * b % m[i]; x = x + c[i] * m_prod; m_prod *= m[i] } (x, c) } fn factorize(mut n: i64, pfs: &mut HashMap) { let mut p = 2; while p*p <= n { let mut e = 0; while n % p == 0 { n /= p; e += 1; } if e > 0 { *pfs.entry(p).or_insert(0) += e; } p += 1; } if n != 1 { *pfs.entry(n).or_insert(0) += 1; } } fn solve() { // x = a (mod m^e1), x = b (mod m^e2) (e1 < e2) // x = b (mod m^e2) -> x = b (mod m^e1) input! { xy: [(i64, i64); 3], }; let mut map = HashMap::new(); for i in 0..3 { let (x, y) = xy[i]; let mut pfs = HashMap::new(); factorize(y, &mut pfs); for (p, e) in pfs { let q = pow(p, e); let x = x % q; map.orwith(p, || vec![]).push((q, x)); } } let mut a = vec![]; let mut m = vec![]; for (_, mut v) in map.iit() { v.sort(); v.reverse(); let (q, y) = v[0]; for (q, x) in v { if y % q != x { println!("-1"); return; } } a.push(y.l()); m.push(q.l()); } let m_p = m.it().product::(); let d = crt(&a, &m).0; println!("{}", if d == 0 { m_p } else { d }); } fn main() { let t = 1; for _ in 0..t { solve(); } }