记录编号 538184 评测结果 AAAAAAAAAA
题目名称 [HZOI 2015] 帕秋莉的超级多项式 最终得分 100
用户昵称 Gravatar神利·代目 是否通过 通过
代码语言 C++ 运行时间 12.244 s
提交时间 2019-07-22 20:22:16 内存使用 26.07 MiB
显示代码纯文本
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#define ll long long
#define P 998244353
#define g 3
ll inv[263000];
void work_inv(int n) {
	inv[1] = 1;
	for (int i = 2; i <= n; ++i) inv[i] = inv[P % i] * (P - P / i) % P;
}
inline ll POW(ll x, ll y) {
	for (ll z = 1;; x = x * x % P, y >>= 1)
		if (y & 1) z = z * x % P;
		else if (!y) return z;
}

void NTT(int* o, int n, bool op) {
	for (int i = 0, j = 0; i < n; ++i) {
		if (i > j)std::swap(o[i], o[j]);
		for (int k = n >> 1; (j ^= k) < k; k >>= 1);
	}
	for (int i = 2, y; i <= n; i <<= 1)
		for (ll wn = POW(g, op ? (P - 1) / i : P - 1 - (P - 1) / i), j = 0; j < n; j += i)
			for (ll w = 1, k = 0, p = i >> 1; k < p; ++k, w = w * wn % P)
				y = w * o[j + k + p] % P, o[j + k + p] = (o[j + k] - y + P) % P, o[j + k] = (o[j + k] + y) % P;
	if (!op) {
		ll invn = POW(n, P - 2);
		for (int i = 0; i < n; ++i)o[i] = invn * o[i] % P;
	}
}
inline void get_inv(int a[], int b[], int n) {
	if (n == 1) { b[0] = POW(a[0], P - 2); return; }
	static int tmp[262144];
	get_inv(a, b, n >> 1);
	memcpy(tmp, a, sizeof(a[0]) * n);
	memset(tmp + n, 0, sizeof(a[0]) * n);
	NTT(tmp, n << 1, 1), NTT(b, n << 1, 1);
	for (int i = 0, r = n << 1; i < r; ++i) b[i] = (ll)b[i] * (2 - (ll)tmp[i] * b[i] % P + P) % P;
	NTT(b, n << 1, 0), memset(b + n, 0, sizeof(a[0]) * n);
}
inline void get_root(int a[], int b[], int n) {
	if (n == 1) { b[0] = sqrt(a[0]); return; }
	static int tmp[263000], binv[263000];
	get_root(a, b, n >> 1);
	memset(binv, 0, sizeof(binv[0]) * n);
	get_inv(b, binv, n);
	memcpy(tmp, a, sizeof(a[0]) * n);
	memset(tmp + n, 0, sizeof(a[0]) * n);
	NTT(tmp, n << 1, 1), NTT(b, n << 1, 1), NTT(binv, n << 1, 1);
	for (int i = 0, r = n << 1; i < r; ++i) b[i] = inv[2] * (b[i] + (ll)tmp[i] * binv[i] % P) % P;
	NTT(b, n << 1, 0), memset(b + n, 0, sizeof(a[0]) * n);
}
inline void get_ln(int a[], int b[], int n) {
	static int a_[262144], ainv[262144];
	memset(ainv, 0, sizeof(ainv[0]) * (n << 1));
	memset(a_, 0, sizeof(a_[0]) * (n << 1));
	get_inv(a, ainv, n);
	for (int i = 0; i < n - 1; ++i)a_[i] = (ll)a[i + 1] * (i + 1) % P;
	NTT(ainv, n << 1, 1), NTT(a_, n << 1, 1);
	for (int i = 0, r = n << 1; i < r; ++i) b[i] = (ll)a_[i] * ainv[i] % P;
	NTT(b, n << 1, 0);
	for (int i = n - 1; i; --i) b[i] = inv[i] * b[i - 1] % P;
	b[0] = 0, memset(b + n, 0, sizeof(b[0]) * n);
}
inline void get_exp(int a[], int b[], int n) {
	if (n == 1) { b[0] = 1; return; }
	get_exp(a, b, n >> 1);
	static int tmp[262144];
	memset(tmp, 0, sizeof(tmp[0]) * (n << 1));
	get_ln(b, tmp, n);
	for (int i = 0; i < n; ++i) tmp[i] = ((i == 0) - tmp[i] + P + a[i]) % P;
	NTT(tmp, n << 1, 1), NTT(b, n << 1, 1);
	for (int i = 0, r = n << 1; i < r; ++i) b[i] = (ll)b[i] * tmp[i] % P;
	NTT(b, n << 1, 0), memset(b + n, 0, sizeof(b[0]) * n);
}
inline void get_pow(int a[], int b[], int k, int n) {
	static int lna[263000];
	get_ln(a, lna, n);
	for (int i = 0; i < n; ++i) lna[i] = (ll)k * lna[i] % P;
	get_exp(lna, b, n);
}
inline void in(int& TEMP) { int EPX; for (TEMP = getchar(); TEMP < 48 || TEMP>57; TEMP = getchar()); for (TEMP ^= 48, EPX = getchar(); EPX < 58 && EPX>47; EPX = getchar())TEMP = (TEMP << 3) + (TEMP << 1) + (EPX ^ 48); }
int len, n, k, o[263000], o_root[263000], o_inv[263000], o_exp[263000];
int o_inv2[263000], ln[263000], ans[263000];
int t1[263000], t2[263000];
int main() {
	freopen("polynomial.in", "r", stdin);
	freopen("polynomial.out", "w", stdout);
	in(n), in(k); for (int i = 0; i < n; ++i)in(o[i]);
	for (len = 1; len <= n; len <<= 1);
	work_inv(len << 1);
	get_root(o, o_root, len);
	get_inv(o_root, o_inv, len);
	for (int i = n - 1; i; --i)o_inv[i] = inv[i] * o_inv[i - 1] % P;
	o_inv[0] = 0;
	get_exp(o_inv, o_exp, len);
	get_inv(o_exp, o_inv2, len);
	o_inv2[0] = (o_inv2[0] + 1) % P;
	get_ln(o_inv2, ln, len);
	ln[0] = (ln[0] + 1) % P;
	get_pow(ln, ans, k, len);
	for (int i = n; i < len << 1; ++i)ans[i] = 0;
	for (int i = 1; i <= n; ++i) printf("%lld ", (ll)ans[i] * i % P);
	//while(1);
}

/*
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define P 998244353
#define g 3
#define ll long long

//快速幂,PS:0^0 = 1
int mypow(int x, int y) {
	int res = 1;
	while (y) {
		if (y & 1)res = 1ll * res * x % P;
		y >>= 1;
		x = 1ll * x * x % P;
	}
	return res;
}

//o是次数界为n的多项式系数,op=1时,对o做NTT;op=0时,对o做逆NTT
void NTT(int* o, int n, bool op) {
	for (int i = 0, j = 0; i < n; ++i) {
		if (i > j)std::swap(o[i], o[j]);
		for (int k = n >> 1; (j ^= k) < k; k >>= 1);
	}
	for(int i=2,y;i<=n;i<<=1)
		for(ll wn=mypow(g, op?(P-1)/i:P-1-(P-1)/i),j=0;j<n;j+=i)
			for(ll w=1,k=0,p=i>>1;k<p;++k,w=w*wn%P)
				y = w * o[j + k + p] % P, o[j + k + p] = (o[j + k] - y + P) % P, o[j + k] = (o[j + k] + y) % P;
	if (!op) {
		ll invn = mypow(n, P - 2);
		for (int i = 0; i < n; ++i)o[i] = invn * o[i] % P;
	}
}

int lena, lenb;
char a[150010], b[150010];
int A[150010], B[150010], C[150010];
int main() {
	scanf("%s%s", a, b);
	lena = strlen(a);
	for (int i = lena - 1; i >= 0; --i)
		A[lena - i - 1] = a[i];
	lenb = strlen(b);
	for (int i = lenb - 1; i >= 0; --i)
		B[lenb - i - 1] = b[i];

	int len = 1;
	while ((len >> 1) < lena || (len >> 1) < lenb)len <<= 1;

	NTT(A, len, 1), NTT(B, len, 1);

	for (int i = 0; i < len; ++i)
		C[i] = 1ll * A[i] * B[i] % P;
	NTT(C, len, 0);
	for (int i = 0; i < len; ++i) {
		C[i + 1] += C[i] / 10;
		C[i] %= 10;
		putchar(C[i] + '0');
	}
}
*/