Skip to content

Commit f05e218

Browse files
committed
Use shared static variable for dynamic_modint
1 parent a25f6fb commit f05e218

File tree

4 files changed

+57
-47
lines changed

4 files changed

+57
-47
lines changed

cp-algo/algebra/modint.hpp

Lines changed: 23 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,40 @@
11
#ifndef CP_ALGO_ALGEBRA_MODINT_HPP
22
#define CP_ALGO_ALGEBRA_MODINT_HPP
3-
#include "../random/rng.hpp"
4-
#include "affine.hpp"
53
#include "common.hpp"
6-
#include <algorithm>
74
#include <iostream>
8-
#include <optional>
95
namespace cp_algo::algebra {
106
template<typename modint>
117
struct modint_base {
12-
// Would make it virtual, but it affects avx...
13-
int mod() const {
14-
if constexpr(modint::static_mod) {
15-
return modint::static_mod;
16-
} else {
17-
return static_cast<modint*>(this)->mod();
18-
}
8+
static int mod() {
9+
return modint::mod();
1910
}
2011
modint_base(): r(0) {}
2112
modint_base(int64_t rr): r(rr % mod()) {
2213
r = std::min(r, r + mod());
2314
}
2415
modint inv() const {
25-
return bpow(static_cast<modint const&>(*this), mod() - 2);
16+
return bpow(to_modint(), mod() - 2);
2617
}
2718
modint operator - () const {return std::min(-r, mod() - r);}
28-
modint& operator /= (const modint &t) {return *this *= t.inv();}
19+
modint& operator /= (const modint &t) {
20+
return to_modint() *= t.inv();
21+
}
2922
modint& operator *= (const modint &t) {
30-
r *= t.r; r %= mod();
31-
return static_cast<modint&>(*this);
23+
r *= t.r; if(mod()) {r %= mod();}
24+
return to_modint();
3225
}
3326
modint& operator += (const modint &t) {
3427
r += t.r; r = std::min(r, r - mod());
35-
return static_cast<modint&>(*this);
28+
return to_modint();
3629
}
3730
modint& operator -= (const modint &t) {
3831
r -= t.r; r = std::min(r, r + mod());
39-
return static_cast<modint&>(*this);
40-
}
41-
modint operator + (const modint &t) const {
42-
return modint(static_cast<modint const&>(*this)) += t;
43-
}
44-
modint operator - (const modint &t) const {
45-
return modint(static_cast<modint const&>(*this)) -= t;
46-
}
47-
modint operator * (const modint &t) const {
48-
return modint(static_cast<modint const&>(*this)) *= t;
49-
}
50-
modint operator / (const modint &t) const {
51-
return modint(static_cast<modint const&>(*this)) /= t;
32+
return to_modint();
5233
}
34+
modint operator + (const modint &t) const {return modint(to_modint()) += t;}
35+
modint operator - (const modint &t) const {return modint(to_modint()) -= t;}
36+
modint operator * (const modint &t) const {return modint(to_modint()) *= t;}
37+
modint operator / (const modint &t) const {return modint(to_modint()) /= t;}
5338
auto operator <=> (const modint_base &t) const = default;
5439
explicit operator int() const {return r;}
5540
int64_t rem() const {return 2 * r > (uint64_t)mod() ? r - mod() : r;}
@@ -62,12 +47,14 @@ namespace cp_algo::algebra {
6247
if(r >= (uint64_t)mod()) {
6348
r %= mod();
6449
}
65-
return static_cast<modint&>(*this);
50+
return to_modint();
6651
}
6752
uint64_t& setr() {return r;}
6853
uint64_t getr() const {return r;}
6954
private:
7055
uint64_t r;
56+
modint& to_modint() {return static_cast<modint&>(*this);}
57+
modint const& to_modint() const {return static_cast<modint const&>(*this);}
7158
};
7259
template<typename modint>
7360
std::istream& operator >> (std::istream &in, modint_base<modint> &x) {
@@ -81,28 +68,19 @@ namespace cp_algo::algebra {
8168

8269
template<int m>
8370
struct modint: modint_base<modint<m>> {
84-
constexpr static int static_mod = m;
71+
static constexpr int mod() {return m;}
8572
using Base = modint_base<modint<m>>;
8673
using Base::Base;
87-
constexpr static uint64_t static_modmod = 8LL*m*m;
8874
};
8975

9076
struct dynamic_modint: modint_base<dynamic_modint> {
91-
constexpr static int static_mod = 0;
77+
static int mod() {return m;}
78+
static void switch_mod(int nm) {m = nm;}
9279
using Base = modint_base<dynamic_modint>;
93-
int mod() const {return m;}
94-
dynamic_modint(dynamic_modint const& t): Base(t), m(t.m) {}
95-
dynamic_modint(int m, int64_t r): m(m) {
96-
setr() = r % m;
97-
setr() = std::min(setr(), setr() + mod());
98-
}
99-
static auto GF(int mod) {
100-
return [mod](int64_t r) {
101-
return dynamic_modint(mod, r);
102-
};
103-
}
80+
using Base::Base;
10481
private:
105-
int m;
82+
static int m;
10683
};
84+
int dynamic_modint::m = 0;
10785
}
10886
#endif // CP_ALGO_ALGEBRA_MODINT_HPP

cp-algo/algebra/number_theory.hpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
#include "../random/rng.hpp"
44
#include "affine.hpp"
55
#include "modint.hpp"
6-
#include <algorithm>
7-
#include <iostream>
86
#include <optional>
97
namespace cp_algo::algebra {
108
// https://en.wikipedia.org/wiki/Berlekamp-Rabin_algorithm

cp-algo/linalg/vector.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <valarray>
88
#include <iostream>
99
#include <iterator>
10+
#include <cassert>
1011
namespace cp_algo::linalg {
1112
template<class vec, typename base>
1213
struct valarray_base: std::valarray<base> {

verify/number_theory/modsqrt.test.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// @brief Sqrt Mod
2+
#define PROBLEM "https://judge.yosupo.jp/problem/sqrt_mod"
3+
#pragma GCC optimize("Ofast,unroll-loops")
4+
#pragma GCC target("avx2,tune=native")
5+
#include "cp-algo/algebra/number_theory.hpp"
6+
#include <bits/stdc++.h>
7+
8+
using namespace std;
9+
using namespace cp_algo::algebra;
10+
using base = dynamic_modint;
11+
12+
void solve() {
13+
int y, p;
14+
cin >> y >> p;
15+
base::switch_mod(p);
16+
auto res = sqrt(base(y));
17+
if(res) {
18+
cout << *res << "\n";
19+
} else {
20+
cout << -1 << "\n";
21+
}
22+
}
23+
24+
signed main() {
25+
//freopen("input.txt", "r", stdin);
26+
ios::sync_with_stdio(0);
27+
cin.tie(0);
28+
int t = 1;
29+
cin >> t;
30+
while(t--) {
31+
solve();
32+
}
33+
}

0 commit comments

Comments
 (0)