結果
問題 | No.2589 Prepare Integers |
ユーザー | akakimidori |
提出日時 | 2023-12-17 07:27:43 |
言語 | Rust (1.77.0 + proconio) |
結果 |
WA
|
実行時間 | - |
コード長 | 11,538 bytes |
コンパイル時間 | 13,300 ms |
コンパイル使用メモリ | 394,580 KB |
実行使用メモリ | 6,948 KB |
最終ジャッジ日時 | 2024-09-27 07:57:55 |
合計ジャッジ時間 | 14,375 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 1 ms
6,816 KB |
testcase_01 | AC | 1 ms
6,816 KB |
testcase_02 | AC | 1 ms
6,944 KB |
testcase_03 | AC | 1 ms
6,944 KB |
testcase_04 | AC | 64 ms
6,940 KB |
testcase_05 | AC | 37 ms
6,940 KB |
testcase_06 | AC | 27 ms
6,940 KB |
testcase_07 | AC | 24 ms
6,940 KB |
testcase_08 | AC | 16 ms
6,940 KB |
testcase_09 | AC | 15 ms
6,940 KB |
testcase_10 | AC | 15 ms
6,944 KB |
testcase_11 | AC | 15 ms
6,940 KB |
testcase_12 | WA | - |
testcase_13 | WA | - |
testcase_14 | WA | - |
testcase_15 | WA | - |
testcase_16 | WA | - |
testcase_17 | AC | 17 ms
6,944 KB |
testcase_18 | WA | - |
testcase_19 | AC | 15 ms
6,944 KB |
testcase_20 | WA | - |
testcase_21 | AC | 15 ms
6,940 KB |
testcase_22 | WA | - |
testcase_23 | AC | 15 ms
6,940 KB |
testcase_24 | AC | 16 ms
6,944 KB |
testcase_25 | AC | 15 ms
6,940 KB |
testcase_26 | AC | 14 ms
6,940 KB |
testcase_27 | AC | 14 ms
6,944 KB |
ソースコード
// https://codeforces.com/blog/entry/98376 // これを読解する fn run() { input! { m: i64, q: usize, ask: [(u8, i64); q], } let mut base = BasisModM::new(m); for (t, x) in ask { if t == 1 { base.add(x); } else if t == 2 { let ans = base.kth_term(x - 1).unwrap_or(-1); println!("{}", ans); } else { println!("{}", base.count_less(x)); } } } fn main() { run(); } fn gcd(a: i64, b: i64) -> i64 { if b == 0 { a } else { gcd(b, a % b) } } fn inv(a: i64, b: i64) -> i64 { if a == 1 { 1 } else { let c = inv(b % a, a); b + (-b * c + 1) / a } } fn ext_gcd(a: i64, b: i64) -> (i64, i64) { let g = gcd(a, b); let (mut a, mut b) = (a / g, b / g); type Mat = Matrix<i64, 2, 2>; let mut mat = Mat::one(); while a > 0 && b > 0 { let mut p = Mat::one(); if a >= b { let d = a / b; a -= d * b; p[1][0] = -d; } else { let d = b / a; b -= d * a; p[0][1] = -d; } mat = mat * p; } if a > 0 { (mat[0][0], mat[1][0]) } else { (mat[0][1], mat[1][1]) } } pub struct BasisModM { m: i64, len: usize, base: Vec<Vec<i64>>, } const UP: i64 = 1000000000; impl BasisModM { fn new(m: i64) -> Self { assert!(m > 1); let mut up = UP; let mut len = 0; while up > 0 { up /= m; len += 1; } Self { m, len, base: vec![vec![0; len]; len], } } fn add(&mut self, mut v: i64) { let mut b = vec![0; self.len]; for b in b.iter_mut() { *b = v % self.m; v /= self.m; } //println!("add {:?}", b); self.add_rec(b); let m = self.m; for i in (0..self.len).rev() { if self.base[i][i] == 0 { continue; } let src = std::mem::take(&mut self.base[i]); for base in self.base.iter_mut().skip(i + 1) { if base[i] >= src[i] { let d = base[i] / src[i]; for (base, src) in base.iter_mut().zip(src.iter()) { *base = (*base - d * *src + m * m) % m; } } } self.base[i] = src; } /* for b in self.base.iter() { println!("{:?}", b); } println!(); */ } // 0-indexed fn kth_term(&self, x: i64) -> Option<i64> { let mut x = x; let mut d = vec![0; self.len]; for (i, (d, base)) in d.iter_mut().zip(self.base.iter()).enumerate() { if base[i] != 0 { let p = self.m / base[i]; *d = x % p; x /= p; } } if x > 0 { return None; } let m = self.m; let mut ans = vec![0; self.len]; for (i, (d, base)) in d.iter_mut().zip(self.base.iter()).enumerate().rev() { if base[i] == 0 { continue; } let sub = ans[i] / base[i]; for (ans, b) in ans.iter_mut().zip(base.iter()) { *ans = (*ans + (*d - sub) * *b + m * m) % m; } } Some(ans.iter().rfold(0, |s, a| s * m + *a)) } // x 以下であるものの個数を求める fn count_less(&self, mut x: i64) -> i64 { let m = self.m; let base = &self.base; let len = self.len; let mut d = vec![0; len]; for d in d.iter_mut() { *d = x % m; x /= m; } let mut dp = vec![1]; let mut prod = 1; for (i, base) in base.iter().enumerate() { if base[i] != 0 { prod *= m / base[i]; } dp.push(prod); } if x > 0 { return prod; } let mut ans = 0; let mut now = vec![0; len]; for (i, (base, d)) in base.iter().zip(d.iter()).enumerate().rev() { if base[i] != 0 { let sub = now[i] / base[i]; for (now, base) in now.iter_mut().zip(base.iter()) { *now = (*now - sub * *base + m * m) % m; } if *d >= now[i] { let q = (*d - now[i] + base[i] - 1) / base[i]; ans += q * dp[i]; for (now, base) in now.iter_mut().zip(base.iter()) { *now = (*now + q * *base) % m; } } if now[i] > *d { return ans; } } else if now[i] < *d { return ans + dp[i + 1]; } else if now[i] > *d { return ans; } } ans + 1 } fn add_rec(&mut self, mut b: Vec<i64>) { let m = self.m; for i in (0..self.len).rev() { if b[i] == 0 { continue; } if self.base[i][i] == 0 { let g = gcd(m, b[i]); let mul = inv(b[i] / g, m / g); for (base, b) in self.base[i].iter_mut().zip(b.iter_mut()) { *base = *b * mul % m; *b = *b * (m / g) % m; } } else if b[i] % self.base[i][i] == 0 { let mul = b[i] / self.base[i][i]; for (base, b) in self.base[i].iter().zip(b.iter_mut()) { *b = (*b - mul * *base + m * m) % m; } } else { let mut w = self.base[i].clone(); let (s, t) = ext_gcd(b[i], w[i]); let (s, t) = ((s + m) % m, (t + m) % m); for ((b, w), v) in self.base[i].iter_mut().zip(b.iter()).zip(w.iter()) { *b = (*w * s + *v * t) % m; } let mul = b[i] / self.base[i][i]; for (v, a) in b.iter_mut().zip(self.base[i].iter()) { *v = (*v - mul * *a + m * m) % m; } let mul = w[i] / self.base[i][i]; for (w, b) in w.iter_mut().zip(self.base[i].iter()) { *w = (*w - mul * *b + m * m) % m; } self.add_rec(w); let mut a = self.base[i].clone(); let mul = m / a[i]; for a in a.iter_mut() { *a = *a * mul % m; } self.add_rec(a); } } } } // ---------- begin input macro ---------- // reference: https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8 #[macro_export] macro_rules! input { (source = $s:expr, $($r:tt)*) => { let mut iter = $s.split_whitespace(); input_inner!{iter, $($r)*} }; ($($r:tt)*) => { let s = { use std::io::Read; let mut s = String::new(); std::io::stdin().read_to_string(&mut s).unwrap(); s }; let mut iter = s.split_whitespace(); input_inner!{iter, $($r)*} }; } #[macro_export] macro_rules! input_inner { ($iter:expr) => {}; ($iter:expr, ) => {}; ($iter:expr, $var:ident : $t:tt $($r:tt)*) => { let $var = read_value!($iter, $t); input_inner!{$iter $($r)*} }; } #[macro_export] macro_rules! read_value { ($iter:expr, ( $($t:tt),* )) => { ( $(read_value!($iter, $t)),* ) }; ($iter:expr, [ $t:tt ; $len:expr ]) => { (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>() }; ($iter:expr, chars) => { read_value!($iter, String).chars().collect::<Vec<char>>() }; ($iter:expr, bytes) => { read_value!($iter, String).bytes().collect::<Vec<u8>>() }; ($iter:expr, usize1) => { read_value!($iter, usize) - 1 }; ($iter:expr, $t:ty) => { $iter.next().unwrap().parse::<$t>().expect("Parse error") }; } // ---------- end input macro ---------- use std::ops::*; pub trait Zero: Sized + Add<Self, Output = Self> { fn zero() -> Self; fn is_zero(&self) -> bool; } pub trait One: Sized + Mul<Self, Output = Self> { fn one() -> Self; fn is_one(&self) -> bool; } pub trait Ring: Zero + One + Sub<Output = Self> {} pub trait Field: Ring + Div<Output = Self> {} #[derive(Clone, Copy)] pub struct Matrix<T, const R: usize, const C: usize>([[T; C]; R]); impl<T, const R: usize, const C: usize> Matrix<T, R, C> { pub fn new(a: [[T; C]; R]) -> Self { Self(a) } } impl<T, const R: usize, const C: usize> Add for Matrix<T, R, C> where T: Add<Output = T> + Copy, { type Output = Self; fn add(self, rhs: Self) -> Self::Output { let mut res = self.0; for (res, b) in res.iter_mut().flatten().zip(rhs.0.into_iter().flatten()) { *res = *res + b; } Matrix::new(res) } } impl<T, const R: usize, const C: usize> Sub for Matrix<T, R, C> where T: Sub<Output = T> + Copy, { type Output = Self; fn sub(self, rhs: Self) -> Self::Output { let mut res = self.0; for (res, b) in res.iter_mut().flatten().zip(rhs.0.into_iter().flatten()) { *res = *res - b; } Matrix::new(res) } } impl<T, const R: usize, const M: usize, const C: usize> Mul<Matrix<T, M, C>> for Matrix<T, R, M> where T: Zero + Mul<Output = T> + Copy, { type Output = Matrix<T, R, C>; fn mul(self, rhs: Matrix<T, M, C>) -> Self::Output { let mut c = Matrix::new([[T::zero(); C]; R]); for (c, a) in c.0.iter_mut().zip(self.0.iter()) { for (a, b) in a.iter().zip(rhs.0.iter()) { for (c, b) in c.iter_mut().zip(b.iter()) { *c = *c + *a * *b; } } } c } } impl<T, const R: usize, const C: usize> Zero for Matrix<T, R, C> where T: Zero + Copy, { fn zero() -> Self { Self::new([[T::zero(); C]; R]) } fn is_zero(&self) -> bool { self.0.iter().flatten().all(|p| p.is_zero()) } } impl<T, const N: usize> One for Matrix<T, N, N> where T: Zero + One + Copy, { fn one() -> Self { let mut res = Self::new([[T::zero(); N]; N]); for (i, res) in res.0.iter_mut().enumerate() { res[i] = T::one(); } res } fn is_one(&self) -> bool { for (i, res) in self.0.iter().enumerate() { for (j, res) in res.iter().enumerate() { if i == j && !res.is_one() { return false; } if i != j && !res.is_zero() { return false; } } } true } } impl<T, const R: usize, const C: usize> Index<usize> for Matrix<T, R, C> { type Output = [T; C]; fn index(&self, x: usize) -> &Self::Output { &self.0[x] } } impl<T, const R: usize, const C: usize> IndexMut<usize> for Matrix<T, R, C> { fn index_mut(&mut self, x: usize) -> &mut Self::Output { &mut self.0[x] } } impl Zero for i64 { fn zero() -> Self { 0 } fn is_zero(&self) -> bool { *self == 0 } } impl One for i64 { fn one() -> Self { 1 } fn is_one(&self) -> bool { *self == 1 } }