This documentation is automatically generated by online-judge-tools/verification-helper
use std::fmt::{Debug, Display};
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
const MOD: u64 = (1 << 61) - 1;
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct ModIntMersenne {
value: u64,
}
impl Debug for ModIntMersenne {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.value)
}
}
impl Display for ModIntMersenne {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.value)
}
}
impl ModIntMersenne {
pub fn new<T: RemEuclidU64>(x: T) -> Self {
x.rem_euclid_u64()
}
pub fn value(&self) -> u64 {
self.value
}
pub const fn modulus() -> u64 {
MOD
}
#[inline]
fn calc_mod(x: u64) -> u64 {
let tmp = (x >> 61) + (x & MOD);
if tmp >= MOD {
tmp - MOD
} else {
tmp
}
}
/// From <https://qiita.com/keymoon/items/11fac5627672a6d6a9f6>
#[inline]
fn mul(a: u64, b: u64) -> u64 {
let au = a >> 31;
let ad = a & ((1 << 31) - 1);
let bu = b >> 31;
let bd = b & ((1 << 31) - 1);
let mid = ad * bu + au * bd;
let midu = mid >> 30;
let midd = mid & ((1 << 30) - 1);
Self::calc_mod(au * bu * 2 + midu + (midd << 31) + ad * bd)
}
pub fn pow(&self, mut exp: u64) -> Self {
let mut result = ModIntMersenne::new(1);
let mut base = *self;
while exp > 0 {
if exp & 1 == 1 {
result *= base;
}
base *= base;
exp >>= 1;
}
result
}
pub fn inv(&self) -> Self {
self.pow(MOD - 2)
}
}
pub trait RemEuclidU64 {
fn rem_euclid_u64(self) -> ModIntMersenne;
}
macro_rules! impl_rem_for_small_unsigned {
($($t:ty), *) => {
$(
impl RemEuclidU64 for $t {
fn rem_euclid_u64(self) -> ModIntMersenne {
ModIntMersenne {
value: self as u64,
}
}
}
)*
};
}
impl_rem_for_small_unsigned!(u8, u16, u32);
impl RemEuclidU64 for u64 {
fn rem_euclid_u64(self) -> ModIntMersenne {
ModIntMersenne {
value: ModIntMersenne::calc_mod(self),
}
}
}
impl RemEuclidU64 for char {
fn rem_euclid_u64(self) -> ModIntMersenne {
let casted: u64 = self.into();
casted.rem_euclid_u64()
}
}
impl RemEuclidU64 for usize {
fn rem_euclid_u64(self) -> ModIntMersenne {
let casted: u64 = self.try_into().unwrap();
casted.rem_euclid_u64()
}
}
macro_rules! impl_rem_for_signed {
($($t:ty),*) => {
$(
impl RemEuclidU64 for $t {
fn rem_euclid_u64(self) -> ModIntMersenne {
if self < 0 {
-(self.unsigned_abs().rem_euclid_u64())
} else {
self.unsigned_abs().rem_euclid_u64()
}
}
}
)*
};
}
impl_rem_for_signed!(i8, i16, i32, i64, isize);
impl Neg for ModIntMersenne {
type Output = Self;
fn neg(self) -> Self {
if self.value == 0 {
self
} else {
ModIntMersenne {
value: MOD - self.value,
}
}
}
}
impl AddAssign for ModIntMersenne {
fn add_assign(&mut self, rhs: Self) {
self.value += rhs.value;
if self.value >= MOD {
self.value -= MOD;
}
}
}
impl SubAssign for ModIntMersenne {
fn sub_assign(&mut self, rhs: Self) {
if self.value < rhs.value {
self.value += MOD;
}
self.value -= rhs.value;
}
}
impl MulAssign for ModIntMersenne {
fn mul_assign(&mut self, rhs: Self) {
self.value = Self::mul(self.value, rhs.value);
}
}
#[allow(clippy::suspicious_op_assign_impl)]
impl DivAssign for ModIntMersenne {
fn div_assign(&mut self, rhs: Self) {
*self *= rhs.inv();
}
}
macro_rules! impl_assign_to_rem_euclid {
($($t:ty), *) => {
$(
impl AddAssign<$t> for ModIntMersenne {
fn add_assign(&mut self, rhs: $t) {
*self += ModIntMersenne::new(rhs);
}
}
impl SubAssign<$t> for ModIntMersenne {
fn sub_assign(&mut self, rhs: $t) {
*self -= ModIntMersenne::new(rhs);
}
}
impl MulAssign<$t> for ModIntMersenne {
fn mul_assign(&mut self, rhs: $t) {
*self *= ModIntMersenne::new(rhs);
}
}
impl DivAssign<$t> for ModIntMersenne {
fn div_assign(&mut self, rhs: $t) {
*self /= ModIntMersenne::new(rhs);
}
}
)*
};
}
impl_assign_to_rem_euclid!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize);
macro_rules! impl_ops {
($trait:ident, $method: ident, $assign_trait: ident, $assign_method:ident) => {
impl<T> $trait<T> for ModIntMersenne
where
ModIntMersenne: $assign_trait<T>,
{
type Output = Self;
fn $method(mut self, rhs: T) -> Self {
ModIntMersenne::$assign_method(&mut self, rhs);
self
}
}
};
}
impl_ops!(Add, add, AddAssign, add_assign);
impl_ops!(Sub, sub, SubAssign, sub_assign);
impl_ops!(Mul, mul, MulAssign, mul_assign);
impl_ops!(Div, div, DivAssign, div_assign);
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_assign_coercion() {
let mut a = ModIntMersenne::new(1);
a += 1;
assert_eq!(a.value(), 2);
a -= 4;
assert_eq!(a.value(), MOD - 2);
a *= 2;
assert_eq!(a.value(), MOD - 4);
}
#[test]
fn test_binop_coercion() {
let a = ModIntMersenne::new(1);
let b = a + 1;
assert_eq!(b.value(), 2);
let c = b - 4;
assert_eq!(c.value(), MOD - 2);
let d = c * 2;
assert_eq!(d.value(), MOD - 4);
}
#[test]
fn test_pow() {
let a = ModIntMersenne::new(2);
let b = a.pow(3);
assert_eq!(b.value(), 8);
}
#[test]
fn test_div() {
let a = ModIntMersenne::new(2);
let b = a / 2;
assert_eq!(b.value(), 1);
}
}Traceback (most recent call last):
File "/opt/hostedtoolcache/Python/3.13.9/x64/lib/python3.13/site-packages/onlinejudge_verify/documentation/build.py", line 71, in _render_source_code_stat
bundled_code = language.bundle(stat.path, basedir=basedir, options={'include_paths': [basedir]}).decode()
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/hostedtoolcache/Python/3.13.9/x64/lib/python3.13/site-packages/onlinejudge_verify/languages/rust.py", line 288, in bundle
raise NotImplementedError
NotImplementedError