0% found this document useful (0 votes)
11 views5 pages

Mathtool

The document defines a mathematical toolkit in C++ that includes modular arithmetic operations, specifically a modular integer class (ModIntBase) and its operations. It also implements the Chinese Remainder Theorem and combinatorial functions such as factorial and binomial coefficients. Additionally, it includes a prime factorization utility (PrimTable) for integer factorization.

Uploaded by

kuo2004731
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views5 pages

Mathtool

The document defines a mathematical toolkit in C++ that includes modular arithmetic operations, specifically a modular integer class (ModIntBase) and its operations. It also implements the Chinese Remainder Theorem and combinatorial functions such as factorial and binomial coefficients. Additionally, it includes a prime factorization utility (PrimTable) for integer factorization.

Uploaded by

kuo2004731
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 5

namespace mathtool {

// modint referenced from jiangly


template<typename T>
constexpr T power(T a, u64 b) {
T res {1};
for (; b != 0; b /= 2, a *= a) {
if (b % 2 == 1) {
res *= a;
}
}
return res;
}

template<u32 P>
constexpr u32 mulMod(u32 a, u32 b) {
return 1ULL * a * b % P;
}

template<u64 P>
constexpr u64 mulMod(u64 a, u64 b) {
u64 res = a * b - u64(1.L * a * b / P - 0.5L) * P;
res %= P;
return res;
}

template<typename U, U P>
requires std::unsigned_integral<U>
struct ModIntBase {
public:
constexpr ModIntBase() : x {0} {}

template<typename T>
requires std::integral<T>
constexpr ModIntBase(T x_) : x {norm(x_ % T {P})} {}

constexpr static U norm(U x) {


if ((x >> (8 * sizeof(U) - 1) & 1) == 1) {
x += P;
}
if (x >= P) {
x -= P;
}
return x;
}

constexpr U val() const {


return x;
}

constexpr ModIntBase operator-() const {


ModIntBase res;
res.x = norm(P - x);
return res;
}

constexpr ModIntBase inv() const {


return power(*this, P - 2);
}
constexpr ModIntBase &operator*=(const ModIntBase &rhs) & {
x = mulMod<P>(x, rhs.val());
return *this;
}

constexpr ModIntBase &operator+=(const ModIntBase &rhs) & {


x = norm(x + rhs.x);
return *this;
}

constexpr ModIntBase &operator-=(const ModIntBase &rhs) & {


x = norm(x - rhs.x);
return *this;
}

constexpr ModIntBase &operator/=(const ModIntBase &rhs) & {


return *this *= rhs.inv();
}

friend constexpr ModIntBase operator*(ModIntBase lhs, const ModIntBase


&rhs) {
lhs *= rhs;
return lhs;
}

friend constexpr ModIntBase operator+(ModIntBase lhs, const ModIntBase


&rhs) {
lhs += rhs;
return lhs;
}

friend constexpr ModIntBase operator-(ModIntBase lhs, const ModIntBase


&rhs) {
lhs -= rhs;
return lhs;
}

friend constexpr ModIntBase operator/(ModIntBase lhs, const ModIntBase


&rhs) {
lhs /= rhs;
return lhs;
}

friend constexpr std::ostream &operator<<(std::ostream &os, const


ModIntBase &a) {
return os << a.val();
}

friend constexpr bool operator==(ModIntBase lhs, ModIntBase rhs) {


return lhs.val() == rhs.val();
}

friend constexpr bool operator!=(ModIntBase lhs, ModIntBase rhs) {


return lhs.val() != rhs.val();
}

friend constexpr bool operator<(ModIntBase lhs, ModIntBase rhs) {


return lhs.val() < rhs.val();
}
private:
U x;
};

template<u32 P>
using ModInt = ModIntBase<u32, P>;

template<u64 P>
using ModInt64 = ModIntBase<u64, P>;

constexpr u32 P = 1000000007;


using Z = ModInt<P>;

template<class T>
T fpow(T a, u64 b, const LL MOD) {
T res{1};
while (b) {
if (b & 1) res = (res * a) % MOD;
a = (a * a) % MOD;
b >>= 1;
}
return res;
}

void printi28(i28 x) {
string s;
while (x > 0) {
s += (x % 10 + '0');
x /= 10;
}
reverse(all(s));
W(s);
}

struct chinese_remainder_theorem {
i28 solve(vector<i28>& a, vector<i28>& M) {
i28 m = 1;
for (const i28& p : M) {
m *= p;
}
//printi28(m);

i28 res = 0;
for (int i = 0; i < si(a); ++i) {
i28 mi = m / M[i];
res = (res + a[i] * mi % m * fpow(mi, M[i] - 2, M[i])) % m;
}

return res;
}
} CRT;

// comb referenced from jiangly


struct Comb {
int n;
std::vector<Z> _fac;
std::vector<Z> _invfac;
std::vector<Z> _inv;
Comb() : n{0}, _fac{1}, _invfac{1}, _inv{0} {}
Comb(int n) : Comb() {
init(n);
}

void init(int m) {
// m = std::min<i64>(m, Z::getMod() - 1);
if (m <= n) return;
_fac.resize(m + 1);
_invfac.resize(m + 1);
_inv.resize(m + 1);

for (int i = n + 1; i <= m; i++) {


_fac[i] = _fac[i - 1] * i;
}
_invfac[m] = _fac[m].inv();
for (int i = m; i > n; i--) {
_invfac[i - 1] = _invfac[i] * i;
_inv[i] = _invfac[i] * _fac[i - 1];
}
n = m;
}

Z fac(int m) {
if (m > n) init(2 * m);
return _fac[m];
}
Z invfac(int m) {
if (m > n) init(2 * m);
return _invfac[m];
}
Z inv(int m) {
if (m > n) init(2 * m);
return _inv[m];
}
Z binom(int n, int m) {
if (n < m || m < 0) return 0;
return fac(n) * invfac(m) * invfac(n - m);
}
} comb;

// need to be initialized
struct PrimTable {
int n;
vector<int> pr, lp;

inline PrimTable(int n_ = 0) {
n = n_;
lp.resize(n + 1);
init();
}

inline void init() {


if (n < 1) return;
lp[1] = 1;
for (int i = 2; i <= n; ++i) {
if (lp[i] == 0) {
lp[i] = i;
pr.push_back(i);
}
for (int j = 0; i * pr[j] <= n; ++j) {
lp[i * pr[j]] = pr[j];
if (pr[j] == lp[i]) {
break;
}
}
}
}

inline bool isp(int x) {


return x < 2 ? false : (lp[x] == x);
}

inline vector<int> div(int k) {


assert(k <= n);
if (k < 2) return vector<int>();

vector<int> res;
while (k > 1) {
const int f = lp[k];
do {
k /= f;
} while (k % f == 0);
res.push_back(f);
}
return res;
}
};
}
using namespace mathtool;

You might also like