fn run(sc: &mut scanner::Scanner, out: &mut std::io::BufWriter) { let q: u32 = sc.next(); let mut rad = vec![1]; let mut x = vec![0]; let mut valid = vec![true]; for _ in 0..q { let op = sc.next::(); if op == 1 { let m = sc.next::(); let r = sc.next::(); let mut prod = 1; let mut fix = 0; for (p, x) in rad.iter().zip(x.iter()) { fix = (fix + *x * prod) % m; prod = prod * *p % m; } let r = (r - fix).rem_euclid(m); // prod * p + m * q = gcd(m, prod) (mod m) let (p, q) = calc(prod, m); let g = p * prod + m * q; if !*valid.last().unwrap() || r % g != 0 { valid.push(false); rad.push(m); x.push(0); } else { valid.push(true); let m = m / g; rad.push(m); let v = (p * (r / g)).rem_euclid(m); x.push(v); } } else if op == 2 { let k = sc.next::(); for _ in 0..k { rad.pop(); x.pop(); valid.pop(); } } else if op == 3 { let m = sc.next::(); let ans = if *valid.last().unwrap() { let mut s = 0; let mut prod = 1; for (&p, &x) in rad.iter().zip(x.iter()) { s = (s + prod * x) % m; prod = prod * p % m; } s } else { -1 }; writeln!(out, "{}", ans).ok(); } } } // return (a, b) // ax + by = gcd(x, y) fn calc(x: i64, y: i64) -> (i64, i64) { if y == 0 { return (x.signum(), 0); } let q = x.div_euclid(y); let r = x.rem_euclid(y); let p = calc(y, r); (p.1, p.0 - q * p.1) } // ---------- begin scannner ---------- #[allow(dead_code)] mod scanner { use std::str::FromStr; pub struct Scanner<'a> { it: std::str::SplitWhitespace<'a>, } impl<'a> Scanner<'a> { pub fn new(s: &'a String) -> Scanner<'a> { Scanner { it: s.split_whitespace(), } } pub fn next(&mut self) -> T { self.it.next().unwrap().parse::().ok().unwrap() } pub fn next_bytes(&mut self) -> Vec { self.it.next().unwrap().bytes().collect() } pub fn next_chars(&mut self) -> Vec { self.it.next().unwrap().chars().collect() } pub fn next_vec(&mut self, len: usize) -> Vec { (0..len).map(|_| self.next()).collect() } } } // ---------- end scannner ---------- use std::io::Write; use std::collections::*; type Map = BTreeMap; type Set = BTreeSet; type Deque = VecDeque; fn main() { use std::io::Read; let mut s = String::new(); std::io::stdin().read_to_string(&mut s).unwrap(); let mut sc = scanner::Scanner::new(&s); let out = std::io::stdout(); let mut out = std::io::BufWriter::new(out.lock()); run(&mut sc, &mut out); }