被卡时限了 /ll
查看原帖
被卡时限了 /ll
113190
Qiuly楼主2021/3/25 15:32

本地跑 1.5s 左右,感觉卡不动 /ll

不知道是不是做法太劣质了 /dk

// qiuly
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;

#define rez resize
#define pp pop_back
#define pb push_back
#define lep(i, l, r) for (int i = l; i <= r; ++ i)
#define rep(i, r, l) for (int i = r; i >= l; -- i)

const int mod = 998244353;

int mul (int x, int y) {return 1ll * x * y % mod;}
void pls (int &x, int y) {x += y; if (x >= mod) x -= mod;}
int add (int x, int y) {x += y; if (x >= mod) x -= mod; return x;}
int modpow (int x, int y, int res = 1) {
	for (y = (y + mod - 1) % (mod - 1); y; y >>= 1, x = mul (x, x)) if (y & 1) res = mul (res, x);
	return res;
}

const int N = 2e5 + 5;
const int M = 3e3 + 5;

// {{{ poly

const int LogN = 22;
typedef std :: vector <int> poly;
#define Lep(i, l, r) for (int i = l; i < r; ++ i)

int lim, tim, _inv[LogN];
poly w[LogN], rev[LogN];

void init_w (int len = 1 << 20) {
	w[20].rez (len), w[20][0] = 1, w[20][1] = modpow (3, (mod - 1) >> 21);
	Lep (i, 2, len) w[20][i] = mul (w[20][i - 1], w[20][1]);
	rep (i, 19, 0) {w[i].rez (len >>= 1); Lep (j, 0, len) w[i][j] = w[i + 1][j << 1];}
}
void init_r (int len) {
	for (lim = 1, tim = 0; lim < len; lim <<= 1, ++ tim);
	if (rev[tim].size ()) return ;
	rev[tim].rez (lim), _inv[tim] = modpow (lim, -1);
	Lep (i, 0, lim) rev[tim][i] = (rev[tim][i >> 1] >> 1) | ((i & 1) << (tim - 1));
}

void ntt (poly &f, short typ) {
	static ull g[1 << 20 | 5];
	Lep (i, 0, lim) g[rev[tim][i]] = f[i];
	for (int p = 1, t = 0, s = 0; p < lim; p <<= 1, ++ t)
		for (int k = 0; k < lim; k += p << 1) for (int l = k; l < k + p; ++ l)
			s = mul (g[l + p] % mod, w[t][l - k]), g[l + p] = g[l] + mod - s, g[l] += s;
	Lep (i, 0, lim) f[i] = g[i] % mod;
	if (~ typ) return ;
	std :: reverse (++ f.begin (), f.end ());
	Lep (i, 0, lim) f[i] = mul (f[i], _inv[tim]);
}
poly operator * (poly a, poly b) {
	int n = a.size (), m = b.size (), t = n + m - 1;
	init_r (t), a.rez (lim), b.rez (lim), ntt (a, 1), ntt (b, 1);
	Lep (i, 0, lim) a[i] = mul (a[i], b[i]);
	return ntt (a, -1), a.rez (t), a;
}

poly poly_inv (poly a, int k) {
	poly b (1, modpow (a[0], -1)), c;
	for (int n = a.size (), i = 1, l = 2; i < k; i <<= 1, l <<= 1) {
		init_r (l << 1), c.rez (l);
		Lep (i, 0, l) c[i] = i < n ? a[i] : 0;
		c.rez (lim), b.rez (lim), ntt (c, 1), ntt (b, 1);
		Lep (i, 0, lim) b[i] = mul (b[i], add (2, mod - mul (c[i], b[i])));
		ntt (b, -1), b.rez (l);
	}
	return b.rez (k), b;
}
poly poly_deriv (poly a) {
	for (int i = 1, n = a.size (); i < n; ++ i) a[i - 1] = mul (a[i], i);
	return a.pp (), a;
}
poly poly_inter (poly a) {
	for (int i = a.size () - 1; i; -- i) a[i] = mul (a[i - 1], modpow (i, -1));
	return a[0] = 0, a;
}
poly poly_ln (poly a) {
	int n = a.size ();
	poly _0 = poly_deriv (a), _1 = poly_inv (a, n); _0 = _0 * _1;
	return _0 = poly_inter (_0), _0.rez (n), _0;
}
poly poly_exp (poly a) {
	poly b (1, 1), c;
	for (int n = a.size (), i = 1, l = 2; i < n; i <<= 1, l <<= 1) {
		b.rez (l), c = poly_ln (b);
		Lep (j, 0, l) c[j] = add (j < n ? (a[j] + (j == 0)) : 0, mod - c[j]);
		b = b * c;
	}
	return b.rez (a.size ()), b;
}

// }}}

int n, m, invn[N], invf[N], fac[N], dp[M][M];
poly B, f, g;

void init (int L = N - 5) {
	lep (i, 1, L) invn[i] = modpow (i, -1);
	fac[0] = 1;
	lep (i, 1, L) fac[i] = mul (fac[i - 1], i);
	invf[L] = modpow (fac[L], -1);
	rep (i, L, 1) invf[i - 1] = mul (invf[i], i);
}

void bernoulli (int L) {
	B.rez (L + 1);
	lep (i, 0, L) B[i] = invf[i + 1]; B = poly_inv (B, L + 1);
	lep (i, 0, L) B[i] = mul (B[i], fac[i]);
	pls (B[1], 1);
}

void getg (const int lim = min (n, m)) {
	bernoulli (m + 1);
	poly t1 (m + 1); lep (i, 0, m) t1[i] = mul (B[i], invf[i]);
	poly t2 (m + 1); lep (i, 0, m) t2[i] = mul (modpow (n, i + 1), invf[i + 1]);
	g = t1 * t2, g.rez (m + 1), g[0] = 0;
	lep (j, 1, m) g[j] = mod - mul (mul (g[j], fac[j]), invn[j]);
	g = poly_exp (g);
}
void getf (const int lim = min (n, m)) {
	f.rez (m + 1);
	lep (i, 1, lim) {
		int buf = modpow (i, i), tmp = buf;
		for (int j = i, c = 1; j <= m; j += i, tmp = mul (tmp, buf), ++ c)
			pls (f[j], mul (tmp, invn[c]));
	}
	lep (i, 1, m) f[i] = mod - f[i];
	f = poly_exp (f);
}

int main() {
	init_w (), init ();
	scanf ("%d%d", &n, &m);

	getf ();
	getg ();

	f = f * poly_inv (g, m + 1);
	lep (i, 0, m) printf ("%d ", f[i]);
	return puts (""), 0;
}
2021/3/25 15:32
加载中...