你说得对,但是我被卡常了
查看原帖
你说得对,但是我被卡常了
448887
cancan123456楼主2024/4/4 14:44
#include <cstdio>
#include <vector>
#include <algorithm>
using std::scanf;
using std::printf;
using std::vector;
using std::reverse;
using std::max;
typedef long long ll;
const ll mod = 998244353, g = 3;
const ll invg = 332748118, sqrt_1 = 911660635;
const ll inv2 = 499122177, inv_sqrt_1 = 86583718;
ll pow(ll a, ll b) {
	ll ans = 1;
	while (b != 0) {
		if ((b & 1) == 1) {
			ans = ans * a % mod;
		}
		a = a * a % mod;
		b = b / 2;
	}
	return ans;
}
ll inv(ll x) {
	return pow(x, mod - 2);
}
void swap(ll & a, ll & b) {
	a ^= b ^= a ^= b;
}
vector < ll > __Poly_rev[27], __Poly_power_of_g[27], __Poly_power_of_inv_g[27];
void get_rev(int len) {
	if (__Poly_rev[len].empty()) {
		__Poly_rev[len].resize(1 << len);
		__Poly_rev[len][0] = 0;
		for (int i = 0; i < (1 << len); i++) {
			__Poly_rev[len][i] = (__Poly_rev[len][i >> 1] >> 1) | ((i & 1) << (len - 1));
		}
	}
}
void get_power_of_g(int len) {
	if (__Poly_power_of_g[len].empty()) {
		__Poly_power_of_g[len].resize(1 << len);
		__Poly_power_of_inv_g[len].resize(1 << len);
		__Poly_power_of_g[len][0] = __Poly_power_of_inv_g[len][0] = 1;
		ll w = pow(g, (mod - 1) / (1 << (len + 1))), inv_w = pow(w, mod - 2);
		for (int i = 1; i < (1 << len); i++) {
			__Poly_power_of_g[len][i] = __Poly_power_of_g[len][i - 1] * w % mod;
			__Poly_power_of_inv_g[len][i] = __Poly_power_of_inv_g[len][i - 1] * inv_w % mod;
		}
	}
}
int get_length(int n) {
	for (int i = 0; ; i++) {
		if (n <= (1 << i)) {
			return i;
		}
	}
}
class Poly {
	public:
		vector < ll > a;
		int len, n;
		Poly() {
			len = 0;
			n = 1 << len;
			a.push_back(0);
			get_rev(len);
		}
		void set_length(int len_, bool clear = false) {
			if (clear) {
				a.resize(1 << len_);
			} else {
				if (len < len_) {
					a.insert(a.end(), (1 << len_) - (1 << len), 0);
				} else {
					a.erase(a.begin() + (1 << len_), a.end());
				}
			}
			n = 1 << len_;
			len = len_;
			get_rev(len);
		}
		Poly(const vector < ll > & vec) {
			set_length(get_length(vec.size()), true);
			for (int i = 0; i < (int)vec.size(); i++) {
				a[i] = vec[i];
			}
		}
		ll & operator [] (const int & i) {
			return a[i];
		}
		ll operator [] (const int & i) const {
			return a[i];
		}
		void NTT(int inv) {
			for (int i = 0; i < (1 << len); i++) {
				if (__Poly_rev[len][i] < i) {
					swap(a[i], a[__Poly_rev[len][i]]);
				}
			}
			for (int i = 0; i < len; i++) {
				get_power_of_g(i);
			}
			for (int mid = 1, logmid = 0; mid < (1 << len); mid <<= 1, logmid++) {
				for (int i = 0; i < (1 << len); i += 2 * mid) {
					for (int j = 0; j < mid; j++) {
						ll w;
						if (inv != -1) {
							w = __Poly_power_of_g[logmid][j];
						} else {
							w = __Poly_power_of_inv_g[logmid][j];
						}
						ll x = a[i + j];
						ll y = a[i + mid + j] * w % mod;
						a[i + j] = (x + y) % mod;
						a[i + mid + j] = (x - y + mod) % mod;
					}
				}
			}
			if (inv == -1) {
				ll inv_n = pow(1 << len, mod - 2);
				for (int i = 0; i < (1 << len); i++) {
					a[i] = a[i] * inv_n % mod;
				}
			}
		}
};
void print(const Poly & a) {
	for (int i = 0; i < a.n; i++) {
		printf("%lld ", a[i]);
//		if (a[i] < mod / 2) {
//			printf("%lld ", a[i]);
//		} else {
//			printf("-%lld ", mod - a[i]);
//		}
	}
	putchar(10);
}
Poly set_length(const Poly & a, const int & len) {
	static Poly b;
	b = a;
	b.set_length(len);
	return b;
}
void unify_length(const Poly & a, const Poly & b, Poly & x, Poly & y, Poly & c) {
	x = a;
	x.set_length(max(a.len, b.len));
	y = b;
	y.set_length(max(a.len, b.len));
	c.set_length(max(a.len, b.len), true);
}
Poly Add(const Poly & a, const Poly & b) {
	static Poly x, y, c;
	unify_length(a, b, x, y, c);
	for (int i = 0; i < x.n; i++) {
		c[i] = (x[i] + y[i]) % mod;
	}
	return c;
}
Poly Sub(const Poly & a, const Poly & b) {
	static Poly x, y, c;
	unify_length(a, b, x, y, c);
	for (int i = 0; i < x.n; i++) {
		c[i] = (x[i] - y[i] + mod) % mod;
	}
	return c;
}
Poly Mult(const Poly & a, const ll & b) {
	static Poly c;
	c = a;
	for (int i = 0; i < c.n; i++) {
		c[i] = c[i] * b % mod;
	}
	return c;
}
Poly Mult(const ll & b, const Poly & a) {
	static Poly c;
	c = a;
	for (int i = 0; i < c.n; i++) {
		c[i] = c[i] * b % mod;
	}
	return c;
}
Poly Mult(const Poly & a, const Poly & b) {
	static Poly x, y, c;
	unify_length(a, b, x, y, c);
	x.set_length(x.len + 1);
	y.set_length(y.len + 1);
	c.set_length(c.len + 1);
	x.NTT(1);
	y.NTT(1);
	for (int i = 0; i < x.n; i++) {
		c[i] = x[i] * y[i] % mod;
	}
	c.NTT(-1);
	return c;
}
Poly MultMod(const Poly & a, const Poly & b) {
	static Poly c;
	c = Mult(a, b);
	c.set_length(c.len - 1);
	return c;
}
void Divide(const Poly & a, Poly & b, int l, int r, int log2) {
	static Poly temp1, temp2;
	if (l == r - 1) {
		if (l == 0) {
			b[0] = 1;
		}
	} else {
		int mid = (l + r) / 2;
		Divide(a, b, l, mid, log2 - 1);
		temp1.set_length(log2, true);
		for (int i = 0; i < r - l; i++) {
			temp1[i] = a[i];
		}
		temp2.set_length(log2, true);
		for (int i = l; i < mid; i++) {
			temp2[i - l] = b[i];
		}
		temp1 = Mult(temp1, temp2);
		for (int i = mid; i < r; i++) {
			b[i] = (b[i] + temp1[i - l]) % mod;
		}
		Divide(a, b, mid, r, log2 - 1);
	}
}
Poly Inverse(const Poly & a) {
	static Poly ans[2];
	ans[0].set_length(0);
	ans[0][0] = pow(a[0], mod - 2);
	for (int i = 1, t; i <= a.len; i++) {
		t = i & 1;
		ans[t] = Sub(Mult(ans[t ^ 1], 2), MultMod(Mult(ans[t ^ 1], ans[t ^ 1]), set_length(a, i)));
	}
	return ans[a.len & 1];
}
Poly Differential(const Poly & a) {
	static Poly b;
	b.set_length(a.len);
	for (int i = a.n - 1; i > 0; i--) {
		b[i - 1] = a[i] * i % mod;
	}
	return b;
}
Poly Integral(const Poly & a) {
	static Poly b;
	b.set_length(a.len);
	for (int i = 1; i < a.n; i++) {
		b[i] = a[i - 1] * pow(i, mod - 2) % mod;
	}
	return b;
}
Poly Natural_Log(const Poly & a) {
	return Integral(MultMod(Differential(a), Inverse(a)));
}
Poly Exp(const Poly & a) {
	static Poly ans[2], one;
	ans[0].set_length(0);
	ans[0][0] = 1;
	for (int i = 1, t; i <= a.len; i++) {
		t = i & 1;
		ans[t ^ 1].set_length(i);
		one.set_length(i);
		one[0] = 1;
		ans[t] = MultMod(ans[t ^ 1], Add(Sub(one, Natural_Log(ans[t ^ 1])), set_length(a, i)));
	}
	return ans[a.len & 1];
}
Poly __Power(const Poly & a, const ll & k) {
	return Exp(Mult(Natural_Log(a), k));
}
Poly Power(const Poly & a, const ll & k0, const ll & k1, const ll & k2) {
	static Poly temp, one;
	int t = -1;
	ll b;
	for (int i = 0; i < a.n; i++) {
		if (a[i] != 0) {
			t = i;
			b = a[i];
			break;
		}
	}
	if (t * k2 >= a.n || t == -1) {
		one.set_length(a.len);
		return one;
	}
	temp = a;
	for (int i = t; i < temp.n; i++) {
		temp[i - t] = temp[i];
	}
	for (int i = temp.n - t; i < temp.n; i++) {
		temp[i] = 0;
	}
	ll inv_b = pow(b, mod - 2);
	for (int i = 0; i < temp.n; i++) {
		temp[i] = temp[i] * inv_b % mod;
	}
	temp = __Power(temp, k0);
	ll b_k = pow(b, k1);
	for (int i = 0; i < temp.n; i++) {
		temp[i] = temp[i] * b_k % mod;
	}
	for (int i = temp.n - t * k0 - 1; i >= 0; i--) {
		temp[i + t * k0] = temp[i];
	}
	for (int i = 0; i < t * k0 && i < temp.n; i++) {
		temp[i] = 0;
	}
	return temp;
}
namespace Cipolla {
	namespace Random {
		ll seed = 2;
		ll rand() {
			return seed = (seed * 25214903917 + 11) & ((1LL << 48) - 1);
		}
	}
	ll w;
	struct Complex {
		ll a, b;
	};
	Complex operator * (const Complex & a, const Complex & b) {
		Complex c;
		c.a = (a.a * b.a % mod + w * a.b % mod * b.b % mod) % mod;
		c.b = (a.b * b.a % mod + a.a * b.b % mod) % mod;
		return c;
	}
	Complex pow(Complex a, ll b) {
		Complex ans;
		ans.a = 1;
		while (b != 0) {
			if ((b & 1) == 1) {
				ans = ans * a;
			}
			b /= 2;
			a = a * a;
		}
		return ans;
	}
	ll Legendre(ll n) {
		return ::pow(n, (mod - 1) / 2);
	}
	ll Solve(ll n) {
		if (n == 0) {
			return 0;
		} else {
			ll a;
			while (true) {
				a = Random::rand() % mod;
				w = (a * a % mod - n + mod) % mod;
				if (Legendre(w) == mod - 1) {
					break;
				}
			}
			Complex res;
			res.a = a;
			res.b = 1;
			res = pow(res, (mod + 1) / 2);
			ll ans = res.a;
			if (ans < mod - ans) {
				return ans;
			} else {
				return mod - ans;
			}
		}
	}
}
Poly Sqrt(const Poly & a) {
	static Poly ans[2];
	ans[0].set_length(0);
	ans[0][0] = Cipolla::Solve(a[0]);
	for (int i = 1, t; i <= a.len; i++) {
		t = i & 1;
		ans[t] = MultMod(Add(set_length(a, i), Mult(ans[t ^ 1], ans[t ^ 1])), Inverse(Mult(2, set_length(ans[t ^ 1], i))));
	}
	return ans[a.len & 1];
}
void Div(Poly f, Poly g, Poly & q, Poly & r) {
	int n = f.a.size();
	for (int i = f.a.size() - 1; i >= 0; i--) {
		if (f[i] != 0) {
			n = i;
		}
	}
	int m = g.a.size();
	for (int i = f.a.size() - 1; i >= 0; i--) {
		if (g[i] != 0) {
			n = i;
		}
	}
	reverse(f.a.begin(), f.a.begin() + n + 1);
	reverse(g.a.begin(), g.a.begin() + m + 1);
	q = Mult(f, Inverse(set_length(g, f.len)));
	for (int i = n - m + 1; i < q.n; i++) {
		q[i] = 0;
	}
	r = Sub(f, Mult(g, q));
	for (int i = 0; i <= m - 1; i++) {
		r[i] = r[i + n - m + 1];
	}
	for (int i = m; i < r.n; i++) {
		r[i] = 0;
	}
	reverse(q.a.begin(), q.a.begin() + (n - m) + 1);
	reverse(r.a.begin(), r.a.begin() + (m - 1) + 1);
}
Poly sin(const Poly & a) {
	static Poly exp_ia;
	exp_ia = Exp(Mult(a, sqrt_1));
	return Mult(Sub(exp_ia, Inverse(exp_ia)), inv2 * inv_sqrt_1 % mod);
}
Poly cos(const Poly & a) {
	static Poly exp_ia;
	exp_ia = Exp(Mult(a, sqrt_1));
	return Mult(Add(exp_ia, Inverse(exp_ia)), inv2);
}
Poly arcsin(const Poly & a) {
	static Poly one;
	one.set_length(a.len);
	one[0] = 1;
	return Integral(MultMod(Differential(a), Inverse(Sqrt(Sub(one, MultMod(a, a))))));
}
Poly arctan(const Poly & a) {
	static Poly one;
	one.set_length(a.len);
	one[0] = 1;
	return Integral(MultMod(Differential(a), Inverse(Add(one, MultMod(a, a)))));
}
struct PolyY {
	vector < ll > vec;
	int len1, len2;
	PolyY() {
		len1 = len2 = 0;
		vec.push_back(0);
	}
	ll & operator () (const int & i, const int & j) {
		return vec[(i << len2) + j];
	}
	ll operator () (const int & i, const int & j) const {
		return vec[(i << len2) + j];
	}
	void set_length(int l1, int l2, bool clear = false) {
		if (clear) {
			vec = vector < ll > (1 << (l1 + l2), 0);
		} else {
			vector < ll > new_vec(1 << (l1 + l2), 0);
			for (int i = 0; i < (1 << l1); i++) {
				for (int j = 0; j < (1 << l2); j++) {
					if (i < (1 << len1) && j < (1 << len2)) {
						new_vec[(i << l2) + j] = vec[(i << len2) + j];
					}
				}
			}
			vec = new_vec;
		}
		len1 = l1;
		len2 = l2;
	}
	PolyY(int l1, int l2, const vector < ll > & a) {
		set_length(l1, l2, true);
		vec = a;
	}
	void NTT(int inv) {
		const int len = len1 + len2;
		get_rev(len);
		for (int i = 0; i < (1 << len); i++) {
			if (__Poly_rev[len][i] < i) {
				swap(vec[i], vec[__Poly_rev[len][i]]);
			}
		}
		for (int i = 0; i < len; i++) {
			get_power_of_g(i);
		}
		for (int mid = 1, logmid = 0; mid < (1 << len); mid <<= 1, logmid++) {
			for (int i = 0; i < (1 << len); i += 2 * mid) {
				for (int j = 0; j < mid; j++) {
					ll w;
					if (inv != -1) {
						w = __Poly_power_of_g[logmid][j];
					} else {
						w = __Poly_power_of_inv_g[logmid][j];
					}
					ll x = vec[i + j];
					ll y = vec[i + mid + j] * w % mod;
					vec[i + j] = (x + y) % mod;
					vec[i + mid + j] = (x - y + mod) % mod;
				}
			}
		}
		if (inv == -1) {
			ll inv_n = pow(1 << len, mod - 2);
			for (int i = 0; i < (1 << len); i++) {
				vec[i] = vec[i] * inv_n % mod;
			}
		}
	}
};
void print(const PolyY & poly) {
	int n = 1 << poly.len1, m = 1 << poly.len2;
	printf("(x: %d y: %d)\n", n, m);
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			const ll x = poly.vec[i * m + j];
			printf("%lld ", x);
//			if (x < mod / 2) {
//				printf("%lld ", x);
//			} else {
//				printf("-%lld ", mod - x);
//			}
		}
		printf("\n");
	}
}
PolyY read() {
	int n, m;
	scanf("%d %d", &n, &m);
	PolyY F;
	F.set_length(get_length(n + 1), get_length(m + 1));
	for (int i = 0; i <= n; i++) {
		for (int j = 0; j <= m; j++) {
			scanf("%lld", &F(i, j));
		}
	}
	return F;
}
PolyY MultMod(PolyY A, PolyY B) {
	A.NTT(1);
	B.NTT(1);
	for (int i = 0; i < (1 << (A.len1 + A.len2)); i++) {
		A.vec[i] = A.vec[i] * B.vec[i] % mod;
	}
	A.NTT(-1);
	return A;
}
Poly BostanMori(int n, PolyY U, PolyY V) {
	if (n == 0) {
		return MultMod(U.vec, Inverse(V.vec));
	} else {
		U.set_length(U.len1 + 1, U.len2 + 1);
		V.set_length(V.len1 + 1, V.len2 + 1);
		PolyY V_prime = V;
		for (int i = 1; i < (1 << V_prime.len1); i += 2) {
			for (int j = 0; j < (1 << V_prime.len2); j++) {
				if (V_prime(i, j) != 0) {
					V_prime(i, j) = mod - V_prime(i, j);
				}
			}
		}
		V_prime.NTT(1);
		U.NTT(1);
		for (int i = 0; i < (1 << (U.len1 + U.len2)); i++) {
			U.vec[i] = U.vec[i] * V_prime.vec[i] % mod;
		}
		U.NTT(-1);
		PolyY U_;
		U_.set_length(U.len1 - 2, U.len2);
		for (int i = 0; i < (1 << U_.len1); i++) {
			for (int j = 0; j < (1 << U_.len2); j++) {
				U_(i, j) = U(2 * i + n % 2, j);
			}
		}
		V.NTT(1);
		for (int i = 0; i < (1 << (U.len1 + U.len2)); i++) {
			V.vec[i] = V.vec[i] * V_prime.vec[i] % mod;
		}
		V.NTT(-1);
		V_prime.set_length(V.len1 - 2, V.len2);
		for (int i = 0; i < (1 << V_prime.len1); i++) {
			for (int j = 0; j < (1 << V_prime.len2); j++) {
				V_prime(i, j) = V(2 * i, j);
			}
		}
		return BostanMori(n / 2, U_, V_prime);
	}
}
PolyY extract(const PolyY & a, int odd) {
	PolyY res;
	res.set_length(a.len1 - 1, a.len2);
	for (int i = 0; i < (1 << res.len1); i++) {
		for (int j = 0; j < (1 << res.len2); j++) {
			res(i, j) = a(2 * i + odd, j);
		}
	}
	return res;
}
Poly MultModT(Poly A, Poly B) {
	A.set_length(A.len + 1);
	B.set_length(B.len + 1);
	A.NTT(-1);
	B.NTT(1);
	for (int i = 0; i < A.n; i++) {
		A[i] = A[i] * B[i] % mod;
	}
	A.NTT(1);
	A.set_length(A.len - 1);
	return A;
}
PolyY MultModT(PolyY A, PolyY B) {
	A.set_length(A.len1 + 1, A.len2 + 1);
	B.set_length(B.len1 + 1, B.len2 + 1);
	A.NTT(-1);
	B.NTT(1);
	for (int i = 0; i < (1 << (A.len1 + A.len2)); i++) {
		A.vec[i] = A.vec[i] * B.vec[i] % mod;
	}
	A.NTT(1);
	A.set_length(A.len1 - 1, A.len2 - 1);
	return A;
}
PolyY set_length(PolyY a, int len1, int len2) {
	a.set_length(len1, len2);
	return a;
}
PolyY BostanMoriT(int n, PolyY U, PolyY V) {
	int l1 = V.len1, l2 = V.len2;
	if (n == 0) {
		return PolyY(l1, l2, MultModT(U.vec, Inverse(V.vec)).a);
	} else {
		int l1 = V.len1, l2 = V.len2;
		PolyY V_prime = V;
		for (int i = 0; i < (1 << l1); i++) {
			for (int j = 0; j < (1 << l2); j++) {
				if (i % 2 == 1 && V(i, j) != 0) {
					V_prime(i, j) = mod - V(i, j);
				}
			}
		}
		V_prime.set_length(l1 + 1, l2 + 1);
		V.set_length(l1 + 1, l2 + 1);
		V.NTT(1);
		V_prime.NTT(1);
		for (int i = 0; i < (1 << (l1 + l2 + 2)); i++) {
			V.vec[i] = V.vec[i] * V_prime.vec[i] % mod;
		}
		V.NTT(-1);
		for (int i = 0; i < (1 << (l1 - 1)); i++) {
			for (int j = 0; j < (1 << (l2 + 1)); j++) {
				V(i, j) = V(2 * i, j);
			}
		}
		V.set_length(l1 - 1, l2 + 1);
		U = BostanMoriT(n / 2, U, V);
		PolyY temp;
		temp.set_length(l1, l2);
		for (int i = 0; i < (1 << (l1 - 1)); i++) {
			for (int j = 0; j < (1 << l2); j++) {
				temp(2 * i + n % 2, j) = U(i, j);
			}
		}
		temp.set_length(l1 + 1, l2 + 1);
		temp.NTT(-1);
		for (int i = 0; i < (1 << (l1 + l2 + 2)); i++) {
			temp.vec[i] = temp.vec[i] * V_prime.vec[i] % mod;
		}
		temp.NTT(1);
		temp.set_length(l1, l2);
		return temp;
	}
}
int main() {
	Poly F, G;
	int n, m;
	scanf("%d %d", &n, &m);
	n++;
	m++;
	G.set_length(get_length(n));
	for (int i = 0; i < n; i++) {
		scanf("%lld", &G[i]);
	}
	F.set_length(get_length(m));
	for (int i = 0; i < m; i++) {
		scanf("%lld", &F[i]);
	}
	PolyY P;
	P.set_length(0, get_length(n) + 1);
	for (int i = 0; i < n; i++) {
		P(0, i) = G[i];
	}
	PolyY V;
	V.set_length(get_length(n), 1);
	V(0, 0) = 1;
	for (int i = 0; i < m; i++) {
		if (F[i] != 0) {
			V(i, 1) = mod - F[i];
		}
	}
	PolyY ans = BostanMoriT(n - 1, P, V);
	for (int i = n - 1; i >= 0; i--) {
		printf("%lld ", ans(i, 0));
	}
	return 0;
}
2024/4/4 14:44
加载中...