求逆求卡常
查看原帖
求逆求卡常
366516
xuyiyang楼主2024/9/22 18:34

vector 封装 NTT NTT 模板 1.32s 这边求逆 5.32s 第一次还 T 了,过了都是 900+ ms。求卡常。

namespace polynomial {
	const int mod = 998244353, G = 3, gi = 332748118;
	vector<int> rev; vector<int> gw;
	int qmi(int x, int y) {
		int res = 1;
		while (y) {
			if (y & 1) res = (LL)res * x % mod;
			y >>= 1; x = (LL)x * x % mod;
		} return res;
	}
	int inv(int x) { return qmi(x, mod - 2); }
	int Rev(int n) {
		int l = 1 << (__lg(n * 2) + 1); rev.resize(l); rev[0] = 0;
		for (int i = 1; i < l; i ++ ) rev[i] = rev[i >> 1] >> 1 | (i & 1 ? l >> 1 : 0);
		return l;
	}
	template <typename T>
	class poly {
		private :
		vector<T> f;
		public :
		T &operator [] (int n) { return f[n]; }
		T operator [] (int n) const { return f[n]; }
		size_t size() const { return f.size(); }
		void resize(int n) { f.resize(n); }
		poly<T> () {}
		poly<T> (int n) { resize(n); }
		void ntt(int type) {
			int n = size();
			for (int i = 0; i < n; i ++ ) if (i < rev[i]) swap(f[i], f[rev[i]]);
			for (int d = 1; d < n; d <<= 1) {
				int wd = qmi(type ? G : gi, (mod - 1) / (d << 1));
				gw.resize(d); gw[0] = 1;
				for (int i = 1; i < d; i ++ ) gw[i] = (LL)gw[i - 1] * wd % mod;
				for (int i = 0; i < n; i += d << 1) {
					for (int j = 0; j < d; j ++ ) {
						int p = f[i | j], q = (LL)gw[j] * f[i | j | d] % mod;
						f[i | j] = p + q >= mod ? p + q - mod : p + q;
						f[i | j | d] = p - q < 0 ? p - q + mod : p - q;
					}
				}
			}
			if (!type) { int iv = inv(n); for (int i = 0; i < n; i ++ ) f[i] = (LL)f[i] * iv % mod; }
		}
		
		poly operator * (const poly& t) const {
			int n = max(size(), t.size()); int l = Rev(n);
			poly<T> f = *this, g = t; f.resize(l), g.resize(l);
			poly<T> res(l); f.ntt(1), g.ntt(1);
			for (int i = 0; i < l; i ++ ) res[i] = (LL)f[i] * g[i] % mod;
			res.ntt(0); res.resize(n); return res;
		}
		poly operator + (const poly& t) const {
			int n = size(), m = t.size(); poly<T> res(max(n, m));
			for (int i = 0; i < max(n, m); i ++ ) res[i] = ((i < n ? f[i] : 0) + (i < m ? t[i] : 0)) % mod;
			return res;
		}
		poly operator - (const poly& t) const {
			int n = size(), m = t.size(); poly<T> res(max(n, m));
			for (int i = 0; i < max(n, m); i ++ ) res[i] = ((i < n ? f[i] : 0) - (i < m ? t[i] : 0) + mod) % mod;
			return res;
		}
	};
	template <typename T>
	poly<T> inv(poly<T> f) {
		int n = f.size(), l = 1; poly<T> res(1); res[0] = inv(f[0]);
		while (l <= n) {
			poly<T> g = res;
			for (int i = 0; i < (int)g.size(); i ++ ) g[i] = (g[i] * 2 >= mod ? g[i] * 2 - mod : g[i] * 2);
			g = g - f * res * res; res = g; l <<= 1; 
		} res.resize(n); return res;
	}
}
using namespace polynomial;

int n;
poly<int> f;

void mian() {
	scanf("%d", &n); n -- ; f.resize(n + 1);
	for (int i = 0; i <= n; i ++ ) scanf("%d", &f[i]);
	f = inv(f); for (int i = 0; i <= n; i ++ ) printf("%d ", f[i]); puts("");
}
2024/9/22 18:34
加载中...