自用
namespace HASH {
const int p = (int)1e9 + 9, base = 233;
ll inv(ll a, int p) {
ll x = 1;
for (int b = p - 2; b; b = b >> 1, a = a * a % p) {
if (b & 1) x = x * a % p;
}
return x;
}
ll B[N], invb, invB[N];
void pre() {
invb = inv(base, p);
B[0] = invB[0] = 1;
for (int i = 1; i < ::N; ++i) {
B[i] = B[i - 1] * base % p;
invB[i] = invB[i - 1] * invb % p;
}
}
struct Hash{
ll hs;
int len;
Hash() { clear(); }
Hash(const ll &hs, const int &len) : hs(hs), len(len) {}
Hash(const Hash &t) : hs(t.hs), len(t.len) {}
void clear() { hs = 0; len = 0; }
void push_front(char c) {
hs = ((ll)c * B[len] + hs) % p;
++len;
}
void push_back(char c) {
++len;
hs = (hs * base + c) % p;
}
};
Hash operator+(const Hash &x, const Hash &y) {
return Hash((x.hs * B[y.len] + y.hs) % p, x.len + y.len);
}
bool operator==(const Hash &x, const Hash &y) { return x.hs == y.hs && x.len == y.len; }
Hash red_front(const Hash &x, const Hash &y) {
assert(x.len >= y.len);
return Hash((x.hs - y.hs * B[x.len - y.len] % p + p) % p, x.len - y.len);
}
Hash red_back(const Hash &x, const Hash &y) {
assert(x.len >= y.len);
return Hash((x.hs - y.hs + p) * invB[y.len] % p, x.len - y.len);
}
}
namespace HASH{
const int p[2] = {(int)1e9 + 7, (int)1e9 + 9}, base[2] = {233, dist(rnd)};
ll B[2][::N], invb[2], invB[2][::N];
void pre() {
invb[0] = inv(base[0], p[0]);
invb[1] = inv(base[1], p[1]);
B[0][0] = B[1][0] = 1;
invB[0][0] = invB[1][0] = 1;
for (int i = 1; i < ::N; ++i) {
B[0][i] = B[0][i - 1] * base[0] % p[0];
B[1][i] = B[1][i - 1] * base[1] % p[1];
invB[0][i] = invB[0][i - 1] * invb[0] % p[0];
invB[1][i] = invB[1][i - 1] * invb[1] % p[1];
}
}
struct Hash{
ll hs[2];
int len;
Hash() { clear(); }
Hash(const ll &hs0, const ll &hs1, const int &len) : len(len) { hs[0] = hs0; hs[1] = hs1; }
Hash(const Hash &t) : len(t.len) { hs[0] = t.hs[0], hs[1] = t.hs[1]; }
void clear() { hs[0] = hs[1] = 0; len = 0; }
void push_front(char c) {
for (int i = 0; i < 2; ++i) hs[i] = ((ll)c * B[i][len] + hs[i]) % p[i];
++len;
}
void push_back(char c) {
++len;
for (int i = 0; i < 2; ++i) hs[i] = (hs[i] * base[i] + c) % p[i];
}
};
Hash operator+(const Hash &x, const Hash &y) {
return Hash((x.hs[0] * B[0][y.len] + y.hs[0]) % p[0], (x.hs[1] * B[1][y.len] + y.hs[1]) % p[1], x.len + y.len);
}
bool operator==(const Hash &x, const Hash &y) { return x.hs[0] == y.hs[0] && x.hs[1] == y.hs[1] && x.len == y.len; }
Hash red_front(const Hash &x, const Hash &y) {
assert(x.len >= y.len);
return Hash((x.hs[0] - y.hs[0] * B[0][x.len - y.len] % p[0] + p[0]) % p[0], (x.hs[1] - y.hs[1] * B[1][x.len - y.len] % p[1] + p[1]) % p[1], x.len - y.len);
}
Hash red_back(const Hash &x, const Hash &y) {
assert(x.len >= y.len);
return Hash((x.hs[0] - y.hs[0] + p[0]) * invB[0][y.len] % p[0], (x.hs[1] - y.hs[1] + p[1]) * invB[1][y.len] % p[1] % p[1], x.len - y.len);
}
}
namespace DLX {
const int R = ::R, C = ::C, N = ::maxn;
struct node {
node *lf, *rg, *up, *dw;
int r, c;
node() { clear(); }
void clear() { lf = rg = up = dw = 0; r = c = 0; }
};
node pool[N + C], *_now = pool;
node *head, *row[R], *col[C];
vector<int> ans;
int m, ect[C];
void clear() {
for (int i = 0; i < R; ++i) row[i] = nullptr;
for (int i = 0; i < C; ++i) col[i] = nullptr;
head = nullptr;
for (node *it = pool; it != _now; ++it) {
it -> clear();
}
_now = pool;
}
node* new_node() { return _now++; }
void linkLR(node *x, node *y) {
x -> rg = y;
y -> lf = x;
}
void removeLR(node *x) {
x -> lf -> rg = x -> rg;
x -> rg -> lf = x -> lf;
}
void resumeLR(node *x) {
x -> lf -> rg = x;
x -> rg -> lf = x;
}
void linkUD(node *x, node *y) {
x -> dw = y;
y -> up = x;
}
void removeUD(node *x) {
x -> up -> dw = x -> dw;
x -> dw -> up = x -> up;
}
void resumeUD(node *x) {
x -> up -> dw = x;
x -> dw -> up = x;
}
void init(int _m) {
m = _m;
for (int i = 0; i <= m; ++i) {
col[i] = new_node();
col[i] -> c = i;
}
for (int i = 0; i <= m; ++i) {
linkLR(col[i], col[(i + 1) % (m + 1)]);
linkUD(col[i], col[i]);
ect[i] = 0;
}
head = col[0];
}
void insert(int _r, int _c) {
node *t = new_node();
t -> r = _r; t -> c = _c;
linkUD(col[_c] -> up, t);
linkUD(t, col[_c]);
if (row[_r] == nullptr) {
row[_r] = t;
linkLR(t, t);
} else {
linkLR(row[_r] -> lf, t);
linkLR(t, row[_r]);
}
++ect[_c];
}
void remove(node *c) {
removeLR(c);
for (node *x = c -> dw; x != c; x = x -> dw) {
for (node *y = x -> rg; y != x; y = y -> rg) {
removeUD(y);
--ect[y -> c];
}
}
}
void resume(node *c) {
for (node *x = c -> up; x != c; x = x -> up) {
for (node *y = x -> lf; y != x; y = y -> lf) {
resumeUD(y);
++ect[y -> c];
}
}
resumeLR(c);
}
bool dance() {
if (head -> rg == head) return true;
node *t = head -> rg;
for (node *x = t -> rg; x != head; x = x -> rg) {
if (ect[x -> c] < ect[t -> c]) t = x;
}
remove(t);
for (node *x = t -> dw; x != t; x = x -> dw) {
ans.emplace_back(x -> r);
for (node *y = x -> rg; y != x; y = y -> rg) {
remove(col[y -> c]);
}
if (dance()) return true;
for (node *y = x -> lf; y != x; y = y -> lf) {
resume(col[y -> c]);
}
ans.pop_back();
}
resume(t);
return false;
}
pair<vector<int>, bool> calc() {
ans.clear();
bool flag = dance();
return make_pair(ans, flag);
}
}
注意:remove
和 resume
的顺序必须正好相反,否则会挂掉,但是神奇的板子题并没有卡。。。。
namespace number_theory {
template<typename T> inline T gcd(T a, T b) {
return b == 0 ? a : gcd(b, a % b);
}
template<typename T> inline T exgcd(T a, T b, T &x, T &y) {
if (b == 0) {
x = 1, y = 0;
return a;
}
T d = exgcd(b, a % b, y, x);
y -= (a / b) * x;
return d;
}
int fpw(ll a, ll b, int mo) {
ll x = 1; a = (a % mo + mo) % mo;
for (; b; b >>= 1, a = a * a % mo) {
if (b & 1) x = x * a % mo;
}
return x;
}
int inv(ll a, int mo) { return fpw(a, mo - 2, mo); }
ll mul(const ll &x, const ll &y, const ll &mo) { return (__int128)x * y % mo; }
pair<pair<ll, ll>, bool> exCRT(vector<ll> a, vector<ll> b, int n) {//means x mod b[i] = a[i] mod a[i]
assert(n > 0);
ll A = a[0], M = b[0];
for (int i = 1; i < n; ++i) {
ll k1, k2, t = a[i] - A;
ll d = exgcd(M, b[i], k1, k2);
if (t % d != 0) return make_pair(make_pair(-1ll, 0ll), false);
ll tM = M / gcd(M, b[i]) * b[i];
A = (mul((mul(t / d, k1, tM) + tM) % tM, M, tM) + A) % tM;
M = tM;
}
return make_pair(make_pair(A, M), true);
}
int Phi(int x) {
int phi = x;
for (int i = 2; i * i <= x; ++i) if (x % i == 0) {
phi = phi - phi / i;
for (; x % i == 0; x /= i);
}
if (x > 1) phi = phi - phi / x;
return phi;
}
vector<pair<int, int>> prime_factorization(int x) {
vector<pair<int, int>> res;
for (int i = 2; i * i <= x; ++i) if (x % i == 0) {
int c = 0;
for (; x % i == 0; x /= i, ++c);
res.emplace_back(i, c);
}
if (x > 1) res.emplace_back(x, 1);
return res;
}
int min_primitive_root(int m) {
int phi = Phi(m);
auto v = prime_factorization(phi);
for (int i = 2; i <= m; ++i) {
bool flag = 1;
for (auto x : v) {
if (fpw(i, phi / x.first, m) == 1) {flag = 0; break; }
}
if (flag) return i;
}
return -1;
}
vector<int> primitive_root(int m) {
vector<int> res;
int phi = Phi(m), mn = -1;
auto v = prime_factorization(phi);
for (int i = 1; i <= m; ++i) if (gcd(i, m) == 1) {
bool flag = 1;
for (auto x : v) {
if (fpw(i, phi / x.first, m) == 1) {flag = 0; break; }
}
if (flag) {
mn = i;
break;
}
}
if (mn == -1) return res;
for (int i = 1; i <= phi; ++i) if (gcd(i, phi) == 1) {
res.push_back(fpw(mn, i, m));
}
sort(res.begin(), res.end());
return res;
}
}
标签:node,const,int,hs,len,板子,Hash From: https://www.cnblogs.com/lazytag/p/17001984.html