多项式开根 0pts 求调,马蜂良好
查看原帖
多项式开根 0pts 求调,马蜂良好
421781
liuzimingc楼主2024/7/23 20:52

RT。感激不尽。

#include <bits/stdc++.h>
 
using namespace std;

namespace liuzimingc {
#define int long long
const int N = 3e6 + 5, MOD = 998244353;
const int GENSHIN = 3;

int n, m, f[N], g[N], inv2;

int qkpow(int a, int b) {
	b %= MOD - 1;
	if (b < 0) return qkpow(qkpow(a, -b), MOD - 2);
	int ans = 1;
	while (b) {
		if (b & 1) ans = ans * a % MOD;
		a = a * a % MOD;
		b >>= 1;
	}
	return ans;
}

namespace poly {
int r[N], h[N], a[N], b[N], c[N], d[N];

void butterfly(int l) {
	for (int i = 1; i < (1 << l); i++)
		r[i] = (r[i >> 1] >> 1) | ((i & 1) << l - 1);
}

void get_rev(int *f, int n) {
	for (int i = 1; i < n; i++)
		if (i < r[i]) swap(f[i], f[r[i]]);
}

void NTT(int *f, int n, int type) {
	get_rev(f, n);
	for (int mid = 1; mid < n; mid <<= 1) {
		int wn = qkpow(GENSHIN, type * (MOD - 1) / (mid << 1));
		for (int i = 0; i < n; i += mid << 1) {
			int w = 1;
			for (int j = 0; j < mid; j++, w = w * wn % MOD) {
				int f1 = f[i + j], f2 = w * f[i + j + mid] % MOD;
				f[i + j] = (f1 + f2) % MOD;
				f[i + j + mid] = (f1 - f2 + MOD) % MOD;
			}
		}
	}
	if (type == 1) return;
	int inv = qkpow(n, MOD - 2);
	for (int i = 0; i < n; i++) f[i] = f[i] * inv % MOD;
}

void derivate(int *f, int n, int *g) {
	for (int i = 0; i < n - 1; i++) g[i] = f[i + 1] * (i + 1) % MOD;
	g[n - 1] = 0;
}

void integrate(int *f, int n, int *g) {
	g[0] = 0;
	for (int i = 1; i < n; i++) g[i] = f[i - 1] * qkpow(i, MOD - 2) % MOD;
}

void mul(int *F, int *G, int n, int m, int *h) {
	int l = __lg(n + m) + 1, len = 1 << l;
	static int f[N], g[N];
	for (int i = 0; i < n; i++) f[i] = F[i];
	for (int i = 0; i < m; i++) g[i] = G[i];
	butterfly(l);
	NTT(f, len, 1); NTT(g, len, 1);
	for (int i = 0; i < len; i++) f[i] = f[i] * g[i] % MOD;
	NTT(f, len, -1);
	for (int i = 0; i < n + m; i++) h[i] = f[i];
}

void inv(int *F, int n, int *g) {
	if (n == 1) {
		g[0] = qkpow(F[0], MOD - 2);
		return;
	}
	inv(F, n + 1 >> 1, g);
	int l = 0, len = 1;
	while (len < (n << 1)) len <<= 1, l++;
	static int f[N];
	for (int i = 0; i < n; i++) f[i] = F[i];
	butterfly(l);
	NTT(f, len, 1); NTT(g, len, 1);
	for (int i = 0; i < len; i++) g[i] = (2 - g[i] * f[i] % MOD + MOD) % MOD * g[i] % MOD;
	NTT(g, len, -1);
	for (int i = n; i < len; i++) g[i] = 0;
}

void sqrt(int *F, int n, int *g) {
	if (n == 1) {
		g[0] = 1;
		return;
	}
	sqrt(F, n + 1 >> 1, g);
	memset(h, 0, sizeof(int) * (n << 1));
	inv(g, n, h);
	int l = 0, len = 1;
	while (len < (n << 1)) len <<= 1, l++;
	static int f[N];
	for (int i = 0; i < n; i++) f[i] = F[i];
	butterfly(l);
	NTT(f, len, 1); NTT(g, len, 1); NTT(h, len, 1);
	for (int i = 0; i < len; i++) g[i] = (g[i] * inv2 % MOD + f[i] * h[i] % MOD * inv2 % MOD) % MOD;
	NTT(g, len, -1);
	for (int i = n; i < len; i++) g[i] = 0;
}

void ln(int *F, int n, int *g) {
	derivate(F, n, a);
	inv(F, n, b);
	mul(a, b, n, n, c);
	integrate(c, n, g);
}
} // namespace poly

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr); cout.tie(nullptr);
	inv2 = qkpow(2, MOD - 2);
	cin >> n;
	for (int i = 0; i < n; i++) cin >> f[i];
	poly::sqrt(f, n, g);
	for (int i = 0; i < n; i++) cout << g[i] << " \n"[i == n - 1];
	return 0;
}
#undef int
} // namespace liuzimingc
    
int main() {
	liuzimingc::main();
	return 0;
}
2024/7/23 20:52
加载中...