多项式板子

多项式专用取模类
struct ModInt {
	static const unsigned P = 998244353, G = 3, GI = 332748118;
	static inline unsigned reduce(unsigned x) { return x < P ? x : x - P; }

	int x;
	ModInt(unsigned x = 0): x(x) {}

	friend ModInt operator-(ModInt x) { return reduce(P - x.x); }
	friend ModInt operator+(ModInt x, ModInt y) { return reduce(x.x + y.x); }
	friend ModInt operator-(ModInt x, ModInt y) { return reduce(P + x.x - y.x); }
	friend ModInt operator*(ModInt x, ModInt y) { return 1ULL * x.x * y.x % P; }
	friend ModInt &operator+=(ModInt &x, ModInt y) { return x = x + y; }
	friend ModInt &operator-=(ModInt &x, ModInt y) { return x = x - y; }
	friend ModInt &operator*=(ModInt &x, ModInt y) { return x = x * y; }

	friend ModInt qpow(ModInt x, int y) { ModInt res = 1; for (; y; y >>= 1, x *= x) if (y & 1) res *= x; return res; }

	friend ModInt operator~(ModInt x) { return qpow(x, P - 2); }
	friend ModInt operator/(ModInt x, ModInt y) { return x * ~y; }
	friend ModInt &operator/=(ModInt &x, ModInt y) { return x *= ~y; }

	friend istream &operator>>(istream &cin, ModInt &x) { return cin >> x.x; }
	friend ostream &operator<<(ostream &cout, ModInt x) { return cout << x.x; }
};
struct Poly: public vector<ModInt> {
	using vector<ModInt>::vector;
	friend Reimu NTT(Poly &F, int o = 0) {
		int len = F.size(), sz = __lg(len);
		vector<ModInt> g(len >> 1); g[0] = 1;
		vector<int> rv(len >> 1);
		for (int i = 1; i < len >> 1; ++i) if ((rv[i] = rv[i >> 1] >> 1 | (i & 1) << sz - 1) < i) ::swap(F[i], F[rv[i]]);
		for (int i = len >> 1, j; i < len; ++i) if ((j = rv[i >> 1] >> 1 | (i & 1) << sz - 1) < i) ::swap(F[i], F[j]);
		for (int k = 1; k <= sz; ++k) {
			int hf = 1 << k - 1;
			ModInt g_ = qpow(ModInt(o ? ModInt::GI : ModInt::G), ModInt::P - 1 >> k);
			for (int i = 1; i < hf; ++i) g[i] = g[i - 1] * g_;
			for (auto f = F.begin(); f != F.end(); f += 1 << k) {
				auto f0 = f, f1 = f + hf, gg = g.begin();
				for (int j = 0; j < hf; ++j) {
					ModInt F0 = *f0, F1 = *f1 * *gg++;
					*f0++ = F0 + F1; *f1++ = F0 - F1;
				}
			}
		}
		if (!o) return;
		ModInt inv = ~ModInt(len);
		for (ModInt &x: F) x *= inv;
	}
	friend Poly &operator+=(Poly &F, TY(Poly) G) {
		if (F.size() < G.size()) F.resize(G.size());
		for (int i = 0; i < G.size(); ++i) F[i] += G[i];
		return F;
	}
	friend Poly &operator-=(Poly &F, TY(Poly) G) {
		if (F.size() < G.size()) F.resize(G.size());
		for (int i = 0; i < G.size(); ++i) F[i] -= G[i];
		return F;
	}
	friend Poly &operator*=(Poly &F, Poly G) {
		if (F.empty() || G.empty()) return F = {};
		int len = F.size() + G.size() - 1, len_ = 1 << __lg(len - 1) + 1;
		F.resize(len_); NTT(F); G.resize(len_); NTT(G);
		for (int i = 0; i < len_; ++i) F[i] *= G[i];
		NTT(F, 1); F.resize(len);
		return F;
	}
	friend Poly operator+(Poly F, TY(Poly) G) { return F += G; }
	friend Poly operator-(Poly F, TY(Poly) G) { return F -= G; }
	friend Poly operator*(Poly F, TY(Poly) G) { return F *= G; }
};
posted @ 2022-11-21 16:33  老莽莽穿一切  阅读(28)  评论(0编辑  收藏  举报