This documentation is automatically generated by online-judge-tools/verification-helper
import cp_library.math.table.__header__
from cp_library.math.mod.mint_cls import mint
from cp_library.math.nt.mod_inv_fn import mod_inv
from itertools import accumulate
class modcomb():
fact: list[int]
fact_inv: list[int]
inv: list[int] = [0,1]
@staticmethod
def precomp(N):
mod = mint.mod
def mod_mul(a,b): return a*b%mod
fact = list(accumulate(range(1,N+1), mod_mul, initial=1))
fact_inv = list(accumulate(range(N,0,-1), mod_mul, initial=mod_inv(fact[N], mod)))
fact_inv.reverse()
modcomb.fact, modcomb.fact_inv = fact, fact_inv
@staticmethod
def extend_inv(N):
N, inv, mod = N+1, modcomb.inv, mint.mod
while len(inv) < N:
j, k = divmod(mod, len(inv))
inv.append(-inv[k] * j % mod)
@staticmethod
def factorial(n: int, /) -> mint:
return mint(modcomb.fact[n])
@staticmethod
def comb(n: int, k: int, /) -> mint:
inv, mod = modcomb.fact_inv, mint.mod
if n < k: return mint.zero
return mint(inv[k] * inv[n-k] % mod * modcomb.fact[n])
nCk = binom = comb
@staticmethod
def comb_with_replacement(n: int, k: int, /) -> mint:
if n <= 0: return mint.zero
return modcomb.nCk(n + k - 1, k)
nHk = comb_with_replacement
@staticmethod
def multinom(n: int, *K: int) -> mint:
nCk, res = modcomb.nCk, mint.one
for k in K: res, n = res*nCk(n,k), n-k
return res
@staticmethod
def perm(n: int, k: int, /) -> mint:
'''Returns P(n,k) mod p'''
if n < k: return mint.zero
return mint(modcomb.fact[n] * modcomb.fact_inv[n-k])
nPk = perm
@staticmethod
def catalan(n: int, /) -> mint:
return mint(modcomb.nCk(2*n,n) * modcomb.fact_inv[n+1])
'''
╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸
https://kobejean.github.io/cp-library
'''
class mint(int):
mod: int
zero: 'mint'
one: 'mint'
two: 'mint'
cache: list['mint']
def __new__(cls, *args, **kwargs):
if 0<= (x := int(*args, **kwargs)) <= 2:
return cls.cache[x]
else:
return cls.fix(x)
@classmethod
def set_mod(cls, mod: int):
mint.mod = cls.mod = mod
mint.zero = cls.zero = cls.cast(0)
mint.one = cls.one = cls.fix(1)
mint.two = cls.two = cls.fix(2)
mint.cache = cls.cache = [cls.zero, cls.one, cls.two]
@classmethod
def fix(cls, x): return cls.cast(x%cls.mod)
@classmethod
def cast(cls, x): return super().__new__(cls,x)
@classmethod
def mod_inv(cls, x):
a,b,s,t = int(x), cls.mod, 1, 0
while b: a,b,s,t = b,a%b,t,s-a//b*t
if a == 1: return cls.fix(s)
raise ValueError(f"{x} is not invertible in mod {cls.mod}")
@property
def inv(self): return mint.mod_inv(self)
def __add__(self, x): return mint.fix(super().__add__(x))
def __radd__(self, x): return mint.fix(super().__radd__(x))
def __sub__(self, x): return mint.fix(super().__sub__(x))
def __rsub__(self, x): return mint.fix(super().__rsub__(x))
def __mul__(self, x): return mint.fix(super().__mul__(x))
def __rmul__(self, x): return mint.fix(super().__rmul__(x))
def __floordiv__(self, x): return self * mint.mod_inv(x)
def __rfloordiv__(self, x): return self.inv * x
def __truediv__(self, x): return self * mint.mod_inv(x)
def __rtruediv__(self, x): return self.inv * x
def __pow__(self, x):
return self.cast(super().__pow__(x, self.mod))
def __neg__(self): return mint.mod-self
def __pos__(self): return self
def __abs__(self): return self
def mod_inv(x, mod):
a,b,s,t = x, mod, 1, 0
while b:
a,b,s,t = b,a%b,t,s-a//b*t
if a == 1: return s % mod
raise ValueError(f"{x} is not invertible in mod {mod}")
from itertools import accumulate
class modcomb():
fact: list[int]
fact_inv: list[int]
inv: list[int] = [0,1]
@staticmethod
def precomp(N):
mod = mint.mod
def mod_mul(a,b): return a*b%mod
fact = list(accumulate(range(1,N+1), mod_mul, initial=1))
fact_inv = list(accumulate(range(N,0,-1), mod_mul, initial=mod_inv(fact[N], mod)))
fact_inv.reverse()
modcomb.fact, modcomb.fact_inv = fact, fact_inv
@staticmethod
def extend_inv(N):
N, inv, mod = N+1, modcomb.inv, mint.mod
while len(inv) < N:
j, k = divmod(mod, len(inv))
inv.append(-inv[k] * j % mod)
@staticmethod
def factorial(n: int, /) -> mint:
return mint(modcomb.fact[n])
@staticmethod
def comb(n: int, k: int, /) -> mint:
inv, mod = modcomb.fact_inv, mint.mod
if n < k: return mint.zero
return mint(inv[k] * inv[n-k] % mod * modcomb.fact[n])
nCk = binom = comb
@staticmethod
def comb_with_replacement(n: int, k: int, /) -> mint:
if n <= 0: return mint.zero
return modcomb.nCk(n + k - 1, k)
nHk = comb_with_replacement
@staticmethod
def multinom(n: int, *K: int) -> mint:
nCk, res = modcomb.nCk, mint.one
for k in K: res, n = res*nCk(n,k), n-k
return res
@staticmethod
def perm(n: int, k: int, /) -> mint:
'''Returns P(n,k) mod p'''
if n < k: return mint.zero
return mint(modcomb.fact[n] * modcomb.fact_inv[n-k])
nPk = perm
@staticmethod
def catalan(n: int, /) -> mint:
return mint(modcomb.nCk(2*n,n) * modcomb.fact_inv[n+1])