Skip to content

Commit

Permalink
mint operations (#137)
Browse files Browse the repository at this point in the history
* mint operations

* mint operations

* clang-format
  • Loading branch information
joaomarcosth9 authored Jun 26, 2024
1 parent df51a02 commit bc83bea
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 9 deletions.
4 changes: 3 additions & 1 deletion Codigos/Primitivas/Modular-Int/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

O Mint é uma classe que representa um número inteiro módulo número inteiro $\text{MOD}$. Ela é útil para evitar overflow em operações de multiplicação e exponenciação, e também para facilitar a implementações.

Ao usar o Mint, você deve passar os valores pra ele **já modulados**, ou seja, valores entre $-\text{MOD}$ e $\text{MOD}-1$, o próprio Mint normaliza depois para ficar entre $0$ e $\text{MOD}-1$.

Para lembrar as propriedades de aritmética modular, consulte a seção Teórico desse Almanaque.

Para usar o Mint, basta criar um tipo com o valor de $\text{MOD}$ desejado. O valor de $\text{MOD}$ deve ser um número inteiro positivo, podendo ser tanto do tipo `int` quanto `long long`.
Expand All @@ -19,4 +21,4 @@ a = a ^ 5; // a.v == 4
a = a - 6; // a.v == 5
```

**Obs**: para operador de divisão, o Mint usa o inverso multiplicativo de $a$ baseado no Teorema de Euler (consulte o Teórico para mais detalhes), que é $a^{\text{MOD}-2}$, ou seja, para isso o $\text{MOD}$ deve ser primo.
**Obs**: para operador de divisão, o Mint usa o inverso multiplicativo de $a$ baseado no Teorema de Euler (consulte o Teórico para mais detalhes), que é $a^{\text{MOD}-2}$, ou seja, para isso o $\text{MOD}$ deve ser primo.
34 changes: 26 additions & 8 deletions Codigos/Primitivas/Modular-Int/mint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,43 @@ template <auto MOD, typename T = decltype(MOD)>
struct Mint {
using m = Mint<MOD, T>;
T v;
Mint(T val = 0) : v(val) { }
Mint(T val = 0) : v(val) {
if (v < 0) v += MOD;
}
bool operator==(m o) const { return v == o.v; }
bool operator!=(m o) const { return v != o.v; }
bool operator<(m o) const { return v < o.v; }
m pwr(m b, ll e) {
m res = 1;
while (e > 0) {
if (e & 1) res = res * b;
b = b * b, e >>= 1;
if (e & 1) res *= b;
b *= b, e >>= 1;
}
return res;
}
friend m operator-(m a, m b) { return (a.v -= b.v) < 0 ? a.v + MOD : a.v; }
friend m operator+(m a, m b) { return a - (MOD - b.v); }
friend m operator*(m a, m b) { return (T)((__int128)a.v * b.v % MOD); }
m &operator+=(m o) {
v -= MOD - o.v;
if (v < 0) v += MOD;
return *this;
}
m &operator-=(m o) {
v -= o.v;
if (v < 0) v += MOD;
return *this;
}
m &operator*=(m o) {
v = (T)((__int128)v * o.v % MOD);
return *this;
}
// se quiser otimizar constante, ao inves de (__int128) use (ll) se o T for `int`
friend m operator/(m a, m b) { return a * b.pwr(b, MOD - 2); }
m &operator/=(m o) { return *this *= o.pwr(o, MOD - 2); }
m &operator^=(ll e) { return *this = pwr(*this, e); }
friend m operator-(m a, m b) { return a -= b; }
friend m operator+(m a, m b) { return a += b; }
friend m operator*(m a, m b) { return a *= b; }
friend m operator/(m a, m b) { return a /= b; }
friend m operator^(m a, ll e) { return a.pwr(a, e); }
};

const int MOD = 998244353;
using mint = Mint<MOD>;
using mint = Mint<MOD>;

0 comments on commit bc83bea

Please sign in to comment.