很长很答辩,各位大佬忍耐一下···
// created on Lucian Xu's Laptop
#include <bits/stdc++.h>
// using namespace std;
typedef unsigned int UI;
typedef unsigned long long ULL;
typedef long long LL;
typedef unsigned long long ULL;
typedef std::pair<int, int> PII;
typedef std::pair<int, LL> PIL;
typedef std::pair<LL, int> PLI;
typedef std::pair<LL, LL> PLL;
typedef std::vector<int> vi;
typedef std::vector<vi> vvi;
typedef std::vector<LL> vl;
typedef std::vector<vl> vvl;
typedef std::vector<PII> vpi;
#define typet typename T
#define typeu typename U
#define types typename... Ts
#define tempt template <typet>
#define tempu template <typeu>
#define temps template <types>
#define tandu template <typet, typeu>
#define rep(i, l, r) for (auto i = (l); i <= (r); i++)
#define per(i, r, l) for (auto i = (r); i >= (l); i--)
#define ff first
#define ss second
#define makepair make_pair
#define pushback push_back
#define endl '\n'
#define all(v) v.begin(), v.end()
#define rall(v) v.rbegin(), v.rend()
#ifdef LOCAL
#include "debug.h"
#else
#define debug(...) \
do { \
} while (false)
#endif
constexpr int N = 2e5 + 10;
constexpr int mod = 998244353;
constexpr int inv2 = (mod + 1) / 2;
constexpr int inf = 0x3f3f3f3f;
constexpr LL INF = 1e18;
const double pi = std::acos(-1);
const double eps = 1e-6;
constexpr int lowbit(int x) { return x & -x; }
constexpr int add(int x, int y) { return x + y < mod ? x + y : x - mod + y; }
constexpr int sub(int x, int y) { return x < y ? mod + x - y : x - y; }
constexpr int mul(LL x, int y) { return x * y % mod; }
constexpr void Add(int& x, int y) { x = add(x, y); }
constexpr void Sub(int& x, int y) { x = sub(x, y); }
constexpr void Mul(int& x, int y) { x = mul(x, y); }
constexpr int pow(int x, int y, int z = 1) {
for (; y; y /= 2) {
if (y & 1) Mul(z, x);
Mul(x, x);
}
return z;
}
temps constexpr int add(Ts... x) {
int y = 0;
(..., Add(y, x));
return y;
}
temps constexpr int mul(Ts... x) {
int y = 1;
(..., Mul(y, x));
return y;
}
tempt bool Max(T& x, const T& y) { return x < y ? x = y, true : false; }
tempt bool Min(T& x, const T& y) { return x > y ? x = y, true : false; }
class polynomial : public vi {
public:
polynomial() = default;
polynomial(const vi& v) : vi(v) {}
polynomial(vi&& v) : vi(std::move(v)) {}
int degree() { return size() - 1; }
void clearzero() {
while (size() && !back()) pop_back();
}
};
polynomial& operator+=(polynomial& a, const polynomial& b) {
a.resize(std::max(a.size(), b.size()), 0);
for (int i = 0; i < b.size(); i++) {
Add(a[i], b[i]);
}
a.clearzero();
return a;
}
polynomial operator+(const polynomial& a, const polynomial& b) {
polynomial ans = a;
return ans += b;
}
polynomial& operator-=(polynomial& a, const polynomial& b) {
a.resize(std::max(a.size(), b.size()), 0);
for (int i = 0; i < b.size(); i++) {
Sub(a[i], b[i]);
}
a.clearzero();
return a;
}
polynomial operator-(const polynomial& a, const polynomial& b) {
polynomial ans = a;
return ans -= b;
}
polynomial& operator*=(polynomial& a, int x) {
if (!x) {
a.resize(1);
a[0] = 0;
return a;
}
for (int i = 0; i < a.size(); i++) {
Mul(a[i], x);
}
return a;
}
polynomial operator*(const polynomial& a, int x) {
polynomial ans = a;
return ans *= x;
}
class ntt_t {
public:
static const int maxbit = 22;
static const int sz = 1 << maxbit;
static const int mod = 998244353;
static const int g = 3;
std::array<int, sz + 10> w;
std::array<int, maxbit + 10> len_inv;
ntt_t() {
int wn = pow(g, (mod - 1) >> maxbit);
w[0] = 1;
for (int i = 1; i <= sz; i++) {
w[i] = mul(w[i - 1], wn);
}
len_inv[maxbit] = pow(sz, mod - 2);
for (int i = maxbit - 1; ~i; i--) {
len_inv[i] = add(len_inv[i + 1], len_inv[i + 1]);
}
}
void operator()(vi& v, int& n, int type) {
int bit = 0;
while ((1 << bit) < n) bit++;
int tot = (1 << bit);
v.resize(tot, 0);
vi rev(tot);
n = tot;
for (int i = 0; i < tot; i++) {
rev[i] = rev[i >> 1] >> 1;
if (i & 1) {
rev[i] |= tot >> 1;
}
}
for (int i = 0; i < tot; i++) {
if (i < rev[i]) {
std::swap(v[i], v[rev[i]]);
}
}
for (int midd = 0; (1 << midd) < tot; midd++) {
int mid = 1 << midd;
int len = mid << 1;
for (int i = 0; i < tot; i += len) {
for (int j = 0; j < mid; j++) {
int w0 = v[i + j];
int w1 = mul(
w[type == 1 ? (j << maxbit - midd - 1) : (len - j << maxbit - midd - 1)],
v[i + j + mid]);
v[i + j] = add(w0, w1);
v[i + j + mid] = sub(w0, w1);
}
}
}
if (type == -1) {
for (int i = 0; i < tot; i++) {
v[i] = mul(v[i], len_inv[bit]);
}
}
}
} NTT;
polynomial& operator*=(polynomial& a, const polynomial& b) {
if (!a.size() || !b.size()) {
a.resize(0);
return a;
}
polynomial tmp = b;
int deg = a.size() + b.size() - 1;
int temp = deg;
// 项数较小直接硬算
if ((LL) a.size() * (LL) b.size() <= (LL) deg * 50LL) {
tmp.resize(0);
tmp.resize(deg, 0);
for (int i = 0; i < a.size(); i++) {
for (int j = 0; j < b.size(); j++) {
tmp[i + j] = add(tmp[i + j], mul(a[i], b[j]));
}
}
a = tmp;
return a;
}
// 项数较多跑 NTT
NTT(a, deg, 1);
NTT(tmp, deg, 1);
for (int i = 0; i < deg; i++) {
Mul(a[i], tmp[i]);
}
NTT(a, deg, -1);
a.resize(temp);
return a;
}
polynomial operator*(const polynomial& a, const polynomial& b) {
polynomial ans = a;
return ans *= b;
}
polynomial inverse(const polynomial& a) {
polynomial ans({pow(a[0], mod - 2)});
polynomial temp;
polynomial tempa;
int deg = a.size();
for (int i = 0; (1 << i) < deg; i++) {
tempa.resize(0);
tempa.resize(1 << i << 1, 0);
for (int j = 0; j != tempa.size() and j != deg; j++) {
tempa[j] = a[j];
}
temp = ans * (polynomial({2}) - tempa * ans);
if (temp.size() > (1 << i << 1)) {
temp.resize(1 << i << 1, 0);
}
temp.clearzero();
std::swap(temp, ans);
}
ans.resize(deg);
return ans;
}
polynomial diffrential(const polynomial& a) {
if (!a.size()) {
return a;
}
polynomial ans(vi(a.size() - 1));
for (int i = 1; i < a.size(); i++) {
ans[i - 1] = mul(a[i], i);
}
return ans;
}
polynomial integral(const polynomial& a) {
polynomial ans(vi(a.size() + 1));
for (int i = 0; i < a.size(); i++) {
ans[i + 1] = mul(a[i], pow(i + 1, mod - 2));
}
return ans;
}
polynomial ln(const polynomial& a) {
polynomial da = diffrential(a);
polynomial inva = inverse(a);
polynomial ans = integral(da * inva);
return ans;
}
polynomial exp(const polynomial& a) {
polynomial ans({1});
polynomial temp;
polynomial tempa;
polynomial tempaa;
int deg = a.size();
for (int i = 0; (1 << i) < deg; i++) {
tempa.resize(0);
tempa.resize(1 << i << 1, 0);
for (int j = 0; j != tempa.size() and j != deg; j++) {
tempa[j] = a[j];
}
tempaa = ans;
tempaa.resize(1 << i << 1);
temp = ans * (tempa + polynomial({1}) - ln(tempaa));
if (temp.size() > (1 << i << 1)) {
temp.resize(1 << i << 1, 0);
}
temp.clearzero();
std::swap(temp, ans);
}
ans.resize(deg);
return ans;
}
int cipolla(int x) {
std::srand(time(0));
auto check = [&](int x) -> bool { return pow(x, (mod - 1) / 2) == 1; };
if (!x) return 0;
if (!check(x)) return -1;
int a, b;
while (1) {
a = rand() % mod;
b = sub(mul(a, a), x);
if (!check(b)) break;
}
PII t = {a, 1};
PII ans = {1, 0};
auto mulp = [&](PII x, PII y) -> PII {
auto [x1, x2] = x;
auto [y1, y2] = y;
int c = add(mul(x1, y1), mul(x2, y2, b));
int d = add(mul(x1, y2), mul(x2, y1));
return {c, d};
};
for (int i = (mod + 1) / 2; i; i >>= 1) {
if (i & 1) ans = mulp(ans, t);
t = mulp(t, t);
}
return std::min(ans.ff, mod - ans.ff);
}
polynomial sqrt(polynomial& a) {
// 能处理低位有零, 非二次剩余的情形 //
int cnt = 0;
for (int i = 0; i < a.size(); i++) {
if (a[i] == 0)
cnt++;
else
break;
}
if (cnt and sqrt(cnt + 2) * sqrt(cnt + 2) != cnt + 2) {
return polynomial({-1});
}
polynomial b(vi(a.size()));
for (int i = cnt; i < a.size(); i++) {
b[i - cnt] = a[i];
}
a = b;
// 迭代 //
polynomial ans({cipolla(a[0])});
if (ans[0] == -1) return ans;
polynomial temp;
polynomial tempa;
polynomial tempaa;
int deg = a.size();
for (int i = 0; (1 << i) < deg; i++) {
tempa.resize(0);
tempa.resize(1 << i << 1, 0);
for (int j = 0; j != tempa.size() and j != deg; j++) {
tempa[j] = a[j];
}
tempaa = ans;
tempaa.resize(1 << i << 1);
temp = (tempa * inverse(tempaa) + ans) * inv2;
if (temp.size() > (1 << i << 1)) {
temp.resize(1 << i << 1, 0);
}
temp.clearzero();
std::swap(temp, ans);
}
if (cnt) {
b.resize(0);
b.resize(deg, 0);
for (int i = cnt - 1; i < deg; i++) {
b[i] = ans[i - cnt + 1];
}
return b;
} else {
ans.resize(deg);
return ans;
}
}
char s[100000];
int main() {
// std::ios::sync_with_stdio(false);
// std::cin.tie(0);
// std::cout.tie(0);
int n, m = 0;
scanf("%lld%s", &n, s + 1);
for (int i = 1, len = strlen(s + 1); i <= len; i++) {
Mul(m, 10);
Add(m, s[i] - '0');
}
debug(m);
polynomial a = (vi(n));
for (int i = 0; i < n; i++) {
// std::cin >> a[i];
scanf("%d", &a[i]);
}
a = ln(a);
a *= m;
a = exp(a);
for (int i = 0; i < n; i++) {
// std::cout << a[i] << ' ';
printf("%d ", a[i]);
}
std::cout << endl;
return 0;
}