板子

自用

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);
    }
}

注意:removeresume 的顺序必须正好相反,否则会挂掉,但是神奇的板子题并没有卡。。。。


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;
    }
}

posted @ 2022-12-24 08:51  lazytag  阅读(62)  评论(0)    收藏  举报