多项式 exp 样例过不去,球球了
查看原帖
多项式 exp 样例过不去,球球了
421781
liuzimingc楼主2024/7/25 20:58

RT。

所有除了 exp 的板子都已经验证正确性。基本仿造多项式 sqrt 写的,样例过不了 /ll

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

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

int n, m, a[N], b[N], c[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], f1[N], f2[N], f3[N], f4[N], f5[N], f6[N], f7[N], f8[N];
int 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 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 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 mul(int *F1, int *F2, int n, int m, int *f3) {
	int l = __lg(n + m) + 1, len = 1 << l;
	for (int i = 0; i < len; i++) f1[i] = 0;
	for (int i = 0; i < n; i++) f1[i] = F1[i];
	for (int i = 0; i < len; i++) f2[i] = 0;
	for (int i = 0; i < m; i++) f2[i] = F2[i];
	butterfly(l);
	NTT(f1, len, 1); NTT(f2, len, 1);
	for (int i = 0; i < len; i++) f1[i] = f1[i] * f2[i] % MOD;
	NTT(f1, len, -1);
	for (int i = 0; i < n + m; i++) f3[i] = f1[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++;
	for (int i = 0; i < len; i++) f4[i] = 0;
	for (int i = 0; i < n; i++) f4[i] = F[i];
	butterfly(l);
	NTT(f4, len, 1); NTT(g, len, 1);
	for (int i = 0; i < len; i++) g[i] = (2 - g[i] * f4[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);
	for (int i = 0; i < n << 1; i++) f5[i] = 0;
	inv(g, n, f5);
	int l = 0, len = 1;
	while (len < n << 1) len <<= 1, l++;
	for (int i = 0; i < len; i++) f6[i] = 0;
	for (int i = 0; i < n; i++) f6[i] = F[i];
	butterfly(l);
	NTT(f6, len, 1); NTT(g, len, 1); NTT(f5, len, 1);
	for (int i = 0; i < len; i++) g[i] = (g[i] + f5[i] * f6[i]) % MOD * inv2 % 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);
}

void exp(int *F, int n, int *g) {
	if (n == 1) {
		g[0] = 1;
		return;
	}
	exp(F, n + 1 >> 1, g);
	for (int i = 0; i < n << 1; i++) f7[i] = 0;
	ln(g, n, f7);
	int l = 0, len = 1;
	while (len < n << 1) len <<= 1, l++;
	for (int i = 0; i < len; i++) f8[i] = 0;
	for (int i = 0; i < n; i++) f8[i] = F[i];
	butterfly(l);
	NTT(f8, len, 1); NTT(g, len, 1); NTT(f7, len, 1);
	for (int i = 0; i < len; i++) g[i] = (1 + f8[i] - f7[i] + MOD) * g[i] % MOD;
	NTT(g, len, -1);
	for (int i = n; i < len; i++) g[i] = 0;
}
} // 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 >> a[i];
	poly::exp(a, n, b);
	for (int i = 0; i < n; i++) cout << b[i] << " \n"[i == n - 1];
	return 0;
}
#undef int
} // namespace liuzimingc
    
int main() {
	liuzimingc::main();
	return 0;
}
2024/7/25 20:58
加载中...