一些模板

这里放一些自己写的代码模板吧。

Modint
template<int Mod, class T = unsigned> struct Modint {
   T v;
   Modint(T _v = 0) : v(_v) {}
   Modint operator -() const {return v ? Mod - v : *this;}
   Modint &operator += (const Modint &x) {return (v += x.v) >= Mod ? v -= Mod : v, *this;}
   Modint &operator -= (const Modint &x) {return (v += Mod - x.v) >= Mod ? v -= Mod : v, *this;}
   Modint &operator *= (const Modint &x) {return v = 1llu * v * x.v % Mod, *this;}
   Modint &operator /= (const Modint &x) {return *this *= x.inv();}
   Modint pow(long long B) const {
       Modint res = 1, base = *this;
       while (B) {
           if (B & 1) res *= base;
           base *= base, B >>= 1;
       }
       return res;
   }
   Modint inv() const {return pow(Mod - 2);}
   friend Modint operator + (const Modint &A, const Modint &B) {return Modint(A) += B;}
   friend Modint operator - (const Modint &A, const Modint &B) {return Modint(A) -= B;}
   friend Modint operator * (const Modint &A, const Modint &B) {return Modint(A) *= B;}
   friend Modint operator / (const Modint &A, const Modint &B) {return Modint(A) /= B;}
   friend istream &operator >> (istream &A, Modint &B) {return A >> B.v;}
   friend ostream &operator << (ostream &A, const Modint &B) {return A << B.v;}
   friend bool operator == (const Modint &A, const Modint &B) {return A.v == B.v;}
   explicit operator bool() const {return v;}
};
typedef Modint<mod> mint;

可以使用 cincout 输出。

FastIO
namespace FastIO {
    const int MaxBuf = 1e6;
    using namespace std;
    class Istream {
    private:
        char buffer[MaxBuf + 5], *p1 = buffer, *p2 = buffer;
        inline char getchar() {
            if (p1 == p2) {
                p1 = buffer;
                p2 = buffer + fread(buffer, 1, MaxBuf, stdin);
            }
            if (p1 == p2) return EOF;
            else return *p1++;
        }
        template<typename Type>
        Type getInteger() {
            Type x = 0;
            bool isNagetive = false;
            char buf = getchar();
            while (buf < '0' || buf > '9') {
                isNagetive = buf == '-' ? true : false;
                buf = getchar();
            }
            while (buf >= '0' && buf <= '9') {
                x = x * 10 + (buf ^ 48);
                buf = getchar();
            }
            return isNagetive ? -x : x;
        }
        template<typename Type>
        Type getFloat() {
            Type left = 0, right = 0;
            bool isNagetive = false;
            char buf = getchar();
            while (buf < '0' || buf > '9') {
                isNagetive = buf == '-' ? true : false;
                buf = getchar();
            }
            while (buf >= '0' && buf <= '9') {
                left = left * 10 + (buf ^ 48);
                buf = getchar();
            }
            if (buf == '.') {
                buf = getchar();
                double mul = 10;
                while (buf >= '0' && buf <= '9') {
                    right += (buf ^ 48) / mul;
                    buf = getchar(), mul *= 10;
                }
            }
            return isNagetive ? -left - right : left + right;
        }
        char getChar() {
            char buf = getchar();
            while (isspace(buf))
                buf = getchar();
            return buf;
        }
        string getString() {
            static char str[MaxBuf + 5], buf, *p;
            string result;
            p = str;
            buf = getchar();
            while (isspace(buf))
                buf = getchar();
            while (!isspace(buf)) {
                *p++ = buf, buf = getchar();
                if (p == str + MaxBuf) {
                    *p = 0;
                    result.append(str);
                    p = str;
                }
            }
            *p = 0;
            result.append(str);
            return result;
        }
    public:
        Istream() {}
        ~Istream() {}
        template<typename Type>
        inline Istream &operator >> (Type &x) {
            if (is_same<Type, char>::value)
                x = getChar();
            else if (is_integral<Type>::value ||
                is_same<Type, __int128_t>::value ||
                is_same<Type, __uint128_t>::value)
                x = getInteger<Type>();
            else if (is_floating_point<Type>::value)
                x = getFloat<Type>();
            return *this;
        }
        inline Istream operator >> (string &x) {
            x = getString();
            return *this;
        }
    };
    class Ostream {
    private:
        char buffer[MaxBuf + 5], *p1 = buffer;
        unsigned precision;
        const double eps = 1e-10;
    #ifndef __WIN32
        void putchar(const char c) {
            if (p1 - buffer == MaxBuf) {
                fwrite(buffer, 1, MaxBuf, stdout);
                p1 = buffer;
            }
            *p1++ = c;
        }
    #endif
        template<typename Type>
        void putInteger(Type x) {
            if (x < 0)
                putchar('-'), x = -x;
            static char buf[50], *p;
            p = buf;
            do *p++ = x % 10, x /= 10; while(x);
            do putchar((*--p) ^ 48); while (p != buf);
        }
        template<typename Type>
        void putFloat(Type x) {
            if (x < 0)
                putchar('-'), x = -x;
            x += x * eps;
            x = roundl(x * powl(10, precision)) / powl(10, precision);
            Type left = floorl(x), right = x - left;
            right += right * eps;
            static char buf[MaxBuf + 5], *p;
            p = buf;
            do {
                *p++ = left - (floorl(left / 10) * 10);
                left /= 10;
            } while (left >= 1);
            do putchar((*--p) ^ 48); while (p != buf);
            if (precision > 0) {
                putchar('.');
                for (unsigned i = 0; i < precision; ++i) {
                    right *= 10;
                    putchar((int)(floorl(right)) ^ 48);
                    right -= floorl(right);
                }
            }
        }
        void putString(string str) {
            int len = str.length();
            for (int i = 0; i < len; ++i)
                putchar(str[i]);
        }
    public:
        Ostream() {precision = 4;}
        ~Ostream() {}
        inline void flush() {
            fwrite(buffer, 1, p1 - buffer, stdout);
        }
        inline void setprecision(unsigned newprecision) {
            precision = newprecision;
        }
        template<typename Type>
        inline Ostream &operator << (const Type x) {
            if (is_same<Type, char>::value)
                putchar(x);
            else if (is_integral<Type>::value ||
                is_same<Type, __int128_t>::value ||
                is_same<Type, __uint128_t>::value)
                putInteger(x);
            return *this;
        }
        inline Ostream &operator << (const float x) {
            return putFloat<float>(x), *this;
        }
        inline Ostream &operator << (const double x) {
            return putFloat<double>(x), *this;
        }
        inline Ostream &operator << (const long double x) {
            return putFloat<long double>(x), *this;
        }
        inline Ostream &operator << (const char *x) {
            return putString(x), *this;
        }
        inline Ostream &operator << (const string x) {
            return putString(x), *this;
        }
    };
    Istream fin;
    Ostream fout;
}
using FastIO::fin;
using FastIO::fout;

用法同 cincout。用 fout.flush() 刷新缓冲区,fout.setprecision() 设置小数位数。

当小数位数过多的时候,超过 \(10^{-6}\) 后不建议使用 fout,精度问题很大。

平时用的代码模板
// Cirno is not baka!
#include <bits/stdc++.h>
#define For(i, a, b) for (int i = (a); i <= (int)(b); ++i)
#define Rof(i, a, b) for (int i = (a); i >= (int)(b); --i)
#define Debug(...) { \
    fprintf(stderr, "Function{%s},line[%d]:\t", __FUNCTION__, __LINE__); \
    fprintf(stderr, __VA_ARGS__); \
    fprintf(stderr, "\n"); \
}
#define FILE(filename) { \
    freopen(#filename ".in", "r", stdin); \
    freopen(#filename ".out", "w", stdout); \
}
#define All(x) x.begin(), x.end()
#define rAll(x) x.rbegin(), x.rend()
#define pii pair<int, int>
#define fi first
#define se second
#define i64 long long
#define mkp make_pair
// #define int long long
#define epb emplace_back
using namespace std;

const int _N = 1e6 + 5, mod = 1e9 + 7, inf = 1e9;
template<typename T> void Max(T &x, T y) {x = max(x, y);}
template<typename T> void Min(T &x, T y) {x = min(x, y);}
template<typename T1, typename T2>
void Addmod(T1 &x, T2 y) {x += y; x >= mod ? x -= mod : x;}
template<typename T1, typename T2>
T1 Add(T1 x, T2 y) {x += y; return x >= mod ? x - mod : x;}

namespace BakaCirno {
    void _() {
    }
}

signed main() {
    // FILE(test);
    cin.tie(0)->sync_with_stdio(0); int T = 1;
    // cin >> T;
    while (T--) BakaCirno::_();
}
计算几何
struct Vec {
    double x, y;
    Vec(double x = 0, double y = 0) : x(x), y(y) {}
    Vec operator + (const Vec &A) const {return Vec(x + A.x, y + A.y);}
    Vec operator - (const Vec &A) const {return Vec(x - A.x, y - A.y);}
    Vec operator * (const double &k) const {return Vec(x * k, y * k);}
    Vec operator / (const double &k) const {return Vec(x / k, y / k);}
    double operator * (const Vec &A) const {return x * A.y - y * A.x;}
    double operator () () const {return hypot(x, y);}
    Vec Turn90() const {return Vec(y, -x);}
    Vec Turn(const double &angle) const
        {return Vec(x * cos(angle) - y * sin(angle), y * cos(angle) + x * sin(angle));}
};
struct Line {
    Vec poi, vec;
    Line(Vec poi = Vec(), Vec vec = Vec()) : poi(poi), vec(vec) {}
    Vec operator * (const Line &B) const {
        const Line &A = *this;
        return A.poi + A.vec * ((B.poi - A.poi) * B.vec / (A.vec * B.vec));
    }
};
struct Circle {
    Vec poi; double R;
    Circle(Vec poi = Vec(), double R = 0) : poi(poi), R(R) {}
    Circle(Vec A, Vec B, Vec C) {
        Line ln1((A + B) / 2, (B - A).Turn90());
        Line ln2((B + C) / 2, (C - B).Turn90());
        poi = ln1 * ln2, R = (A - poi)();
    }
    bool ChkIn(const Vec &A) const {return (A - poi)() <= R;}
};

向量,直线交点,已知三点求圆。

NTT
template<int g, int mod>
struct NTT {
    int lim, tim;
    vector<int> rev;
    int Qpow(int x, int y) {
        int res = 1; x %= mod;
        for (; y; y >>= 1, x = 1ll * x * x % mod)
            if (y & 1) res = 1ll * res * x % mod;
        return res;
    }
    void Init(int up) {
        for (lim = 1, tim = 0; lim < up; lim <<= 1, ++tim);
        rev.resize(lim);
        for (int i = 1; i < lim; ++i)
            rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (tim - 1));
    }
    void do_NTT(vector<int> &A) {
        A.resize(lim);
        for (int i = 1; i < lim; ++i)
            if (i < rev[i]) swap(A[i], A[rev[i]]);
        int A0, A1;
        for (int i = 1; i < lim; i <<= 1) {
            const int w = Qpow(g, (mod - 1) / (i << 1));
            for (int j = 0; j < lim; j += i << 1)
                for (int k = 0, W = 1; k < i; ++k, W = 1ll * w * W % mod) {
                    A0 = (A[j + k] + 1ll * A[j + k + i] * W % mod) % mod;
                    A1 = (A[j + k] - 1ll * A[j + k + i] * W % mod) % mod;
                    A[j + k] = A0, A[j + k + i] = A1;
                }
        }
    }
    void do_INTT(vector<int> &A) {
        do_NTT(A), reverse(A.begin() + 1, A.end());
        const int inv = Qpow(lim, mod - 2);
        for (int i = 0; i < lim; ++i) {
            if (A[i] < 0) A[i] += mod;
            A[i] = 1ll * A[i] * inv % mod;
        }
    }
};
struct Poly {
    static const int g = 3, mod = 998244353, inv2 = 499122177;
    vector<int> A, C, lnB, invB;
    NTT<g, mod> ntt;
    Poly(int deg = 0) : A(vector<int>(deg, 0)) {}
    Poly(const vector<int> A) : A(A) {}
    Poly operator * (Poly ano) {
        int deg = A.size() + ano.A.size() - 1;
        ntt.Init(A.size() + ano.A.size());
        ntt.do_NTT(A), ntt.do_NTT(ano.A);
        Poly res(ntt.lim);
        for (int i = 0; i < ntt.lim; ++i)
            res.A[i] = 1ll * A[i] * ano.A[i] % mod;
        ntt.do_INTT(res.A);
        res.A.resize(deg);
        return res;
    }
    void getInv(int deg, vector<int> &A, vector<int> &B) {
        if (deg == 1) {
            B[0] = ntt.Qpow(A[0], mod - 2);
            return ;
        }
        getInv((deg + 1) >> 1, A, B);
        ntt.Init((deg + 1) << 1);
        C.resize(ntt.lim);
        copy(A.begin(), A.begin() + deg, C.begin());
        fill(C.begin() + deg, C.begin() + ntt.lim, 0);
        ntt.do_NTT(C), ntt.do_NTT(B);
        for (int i = 0; i < ntt.lim; ++i)
            B[i] = 1ll * (2 - 1ll * C[i] * B[i] % mod + mod) % mod * B[i] % mod;
        ntt.do_INTT(B);
        fill(B.begin() + deg, B.begin() + ntt.lim, 0);
    }
    Poly inv() {
        vector<int> A = this->A, B;
        int deg = A.size();
        ntt.Init((deg + 1) << 1);
        A.resize(ntt.lim), B.resize(ntt.lim);
        getInv(deg, A, B);
        B.resize(deg);
        return Poly(B);
    }
    int &operator[] (const int &index) {return A[index];}
    Poly deriv() {
        Poly res(A.size() - 1);
        for (int i = 1; i < (int)A.size(); ++i)
            res[i - 1] = 1ll * A[i] * i % mod;
        return res;
    }
    Poly integ() {
        Poly res(A.size() + 1);
        for (int i = 1; i <= (int)A.size(); ++i)
            res[i] = 1ll * A[i - 1] * ntt.Qpow(i, mod - 2) % mod;
        res[0] = 0;
        return res;
    }
    Poly ln() {return (this->deriv() * this->inv()).integ();}
    void getExp(int deg, vector<int> &A, vector<int> &B) {
        if (deg == 1) {
            B[0] = 1;
            return ;
        }
        getExp((deg + 1) >> 1, A, B);
        B.resize(deg);
        lnB = Poly(B).ln().A;
        ntt.Init((deg + 1) << 1);
        C.resize(ntt.lim);
        copy(A.begin(), A.begin() + deg, C.begin());
        for (int i = 0; i < deg; ++i)
            C[i] = (C[i] - lnB[i] + mod) % mod;
        ++C[0];
        fill(C.begin() + deg, C.begin() + ntt.lim, 0);
        ntt.do_NTT(B), ntt.do_NTT(C);
        for (int i = 0; i < ntt.lim; ++i)
            B[i] = 1ll * B[i] * C[i] % mod;
        ntt.do_INTT(B);
        fill(B.begin() + deg, B.begin() + ntt.lim, 0);
    }
    Poly exp() {
        vector<int> A = this->A, B;
        int deg = A.size();
        ntt.Init((deg + 1) << 1);
        A.resize(ntt.lim), B.resize(ntt.lim);
        getExp(deg, A, B);
        B.resize(deg);
        return Poly(B);
    }
    void getSqrt(int deg, vector<int> &A, vector<int> &B) {
        if (deg == 1) {
            B[0] = 1;
            return ;
        }
        getSqrt((deg + 1) >> 1, A, B);
        ntt.Init((deg + 1) << 1);
        fill(invB.begin(), invB.begin() + ntt.lim, 0);
        getInv(deg, B, invB);
        C.resize(ntt.lim);
        copy(A.begin(), A.begin() + deg, C.begin());
        fill(C.begin() + deg, C.begin() + ntt.lim, 0);
        ntt.do_NTT(C), ntt.do_NTT(invB), ntt.do_NTT(B);
        for (int i = 0; i < ntt.lim; ++i)
            B[i] = (1ll * B[i] * inv2 % mod + 1ll * C[i] * invB[i] % mod * inv2 % mod) % mod;
        ntt.do_INTT(B);
        fill(B.begin() + deg, B.begin() + ntt.lim, 0);
    }
    Poly sqrt() {
        vector<int> A = this->A, B;
        int deg = A.size();
        ntt.Init((deg + 1) << 1);
        A.resize(ntt.lim), B.resize(ntt.lim), invB.resize(ntt.lim);
        getSqrt(deg, A, B);
        B.resize(deg);
        return Poly(B);
    }
};

Poly 内重载了 operator *

随手写的 Format 输出
namespace fmt {
    constexpr void fmt(ostream &out, const char* str) {
        for (const char* i = str; *i != '\0'; ++i) {
            if (*i == '{' || *i == '}') throw "Syntax Error";
            out << *i;
        }
    }
    template<typename T>
    constexpr void fmt(ostream &out, const char* str, const T arg) {
        for (const char* i = str; *i != '\0'; ++i) {
            if ((*i == '{' && *(i + 1) != '}') || *i == '}') throw "Syntax Error";
            if (*i == '{') {out << arg; fmt(out, i + 2); break;}
            out << *i;
        }
    }
    template<typename T, typename ...Args>
    constexpr void fmt(ostream &out, const char* str, const T arg, const Args ...args) {
        for (const char* i = str; *i != '\0'; ++i) {
            if ((*i == '{' && *(i + 1) != '}') || *i == '}') throw "Syntax Error";
            if (*i == '{') {out << arg; fmt(out, i + 2, args...); break;}
            out << *i;
        }
    }
    template<typename ...Args>
    constexpr inline void fmtout(const Args ...args) {fmt(cout, args...);}
    template<typename ...Args>
    constexpr inline void fmterr(const Args ...args) {fmt(cerr, args...);}
}

仅支持了最简单的 format 输出。

posted @ 2023-11-17 09:39  Hanx16Msgr  阅读(21)  评论(0编辑  收藏  举报