QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#5885 | #621. 多项式指数函数 | Qingyu | 100 ✓ | 2575ms | 340284kb | C++17 | 14.5kb | 2021-01-26 17:14:39 | 2021-12-19 07:06:43 |
Judging History
answer
#include <bits/stdc++.h>
typedef long long ll;
#define NTT_MODE +1
#define MTT_MODE -1
constexpr int MODE = NTT_MODE;
const int mod = 998244353;
const int inv2 = (mod + 1) / 2;
const int N = 3e6 + 50;
const int g = 3;
inline int lc(int o) { return o << 1; }
inline int rc(int o) { return o << 1 | 1; }
inline int inc(int x, int y) { x += y - mod; return x + (x >> 31 & mod); }
inline int dec(int x, int y) { x -= y; return x + (x >> 31 & mod); }
inline int mul(int x, int y) { return 1ll * x * y % mod; }
template <int T>
struct fast_io
{
char p[T], q[T], * p1, * p2, * q1, * q2;
fast_io()
{
p1 = p2 = p;
q1 = q, q2 = q + T;
}
inline char gc()
{
return p1 == p2 && (p2 = (p1 = p) + fread(p, 1, T, stdin), p1 == p2) ? EOF : *p1++;
}
inline void pc(char c)
{
if (q1 == q2)
{
fwrite(q, 1, T, stdout);
q1 = q;
}
*q1++ = c;
}
~fast_io()
{
fwrite(q, 1, q1 - q, stdout);
}
};
fast_io<2000000> io;
inline int64_t read()
{
int64_t r = 0, neg = 1;
char ch;
do
{
ch = io.gc();
if (ch == '-') neg = -1;
} while (ch < 48 || ch > 57);
do r = r * 10 + ch - 48, ch = io.gc(); while (ch >= 48 && ch <= 57);
return r * neg;
}
inline void read(char *s)
{
char ch;
do ch = io.gc(); while (!isalpha(ch));
do *s++ = ch, ch = io.gc(); while (isalpha(ch));
*s++ = 0;
}
inline void putint(int x)
{
if (x < 0)
{
io.pc('-');
putint(-x);
return;
}
if (x / 10) putint(x / 10);
io.pc(48 + x % 10);
}
inline void output(int x, char ch = ' ')
{
putint(x);
io.pc(ch);
}
struct Math
{
int fact[N], factinv[N], inv_e[N], pri[N], mu[N], tot;
bool isnt_pri[N];
inline int fastpow(int x, ll p)
{
int res = 1;
while (p)
{
if (p & 1) res = mul(res, x);
x = mul(x, x);
p >>= 1;
}
return res;
}
inline int inv(int x)
{
x %= mod;
if (x < N) return inv_e[x];
return fastpow(x, mod - 2);
}
inline void init()
{
fact[0] = factinv[0] = inv_e[0] = 1;
for (int i = 1; i < N; ++i) fact[i] = mul(i, fact[i - 1]);
factinv[N - 1] = fastpow(fact[N - 1], mod - 2);
for (int i = N - 2; i >= 1; --i) factinv[i] = mul(i + 1, factinv[i + 1]);
for (int i = 1; i < N; ++i) inv_e[i] = mul(fact[i - 1], factinv[i]);
isnt_pri[1] = true; mu[1] = 1;
for (int i = 2; i < N; ++i)
{
if (isnt_pri[i] == false)
{
pri[++tot] = i;
mu[i] = -1;
}
for (int j = 1; j <= tot && i * pri[j] < N; ++j)
{
isnt_pri[i * pri[j]] = true;
if (i % pri[j] == 0)
{
mu[i * pri[j]] = 0;
break;
}
else mu[i * pri[j]] = -mu[i];
}
}
}
} mt;
struct Poly
{
std::vector<int> v;
Poly() { }
Poly(std::vector<int> v) : v(v) {}
Poly(std::initializer_list<int> v) : v(v) {}
inline int deg() const { return v.size() - 1; }
inline void redeg(int k) { v.resize(k + 1); }
inline Poly slice(int k) const
{
if (k < v.size())
return std::vector<int>(v.begin(), v.begin() + k + 1);
std::vector<int> a(v);
a.resize(k + 1);
return a;
}
inline Poly clone() const { return slice(deg()); }
inline void reverse() { std::reverse(v.begin(), v.end()); }
inline void shrink()
{
int c = deg();
while (c >= 0 && v[c] == 0) --c;
v.resize(c + 1);
}
inline int& operator[](int k)
{
if (v.size() <= k) v.resize(k + 1);
return v[k];
}
inline int operator[](int k) const
{
return v.size() <= k ? 0 : v[k];
}
inline void print() const
{
for (auto x : v) output(x);
io.pc('\n');
}
inline Poly inv() const;
inline Poly derivative() const;
inline Poly integration() const;
inline Poly ln() const;
inline Poly exp() const;
inline Poly reverse() const;
inline Poly sqrt() const;
inline std::vector<int> evaluation(const std::vector<int> &vals) const;
inline void interpolation(const std::vector<std::pair<int, int> > &points);
Poly(std::vector<std::pair<int, int> > points) { interpolation(points); }
};
struct NTT
{
int len, k;
int omega[N], omegaInv[N], rev[N];
inline void init(int n)
{
int last_len = len;
len = 1, k = 0;
while (len <= n) len <<= 1, ++k;
if (last_len == len) return;
for (int i = 0; i < len; ++i) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (k - 1));
omega[0] = omegaInv[0] = 1;
const int primitive = mt.fastpow(g, (mod - 1) / len);
for (int i = 1; i < len; ++i) omega[i] = omegaInv[len - i] = mul(omega[i - 1], primitive);
}
inline void operator() (Poly &a, const int *w)
{
if (a.v.size() < len) a.v.resize(len);
int *b = a.v.data();
for (int i = 0; i < len; ++i) if (i < rev[i]) std::swap(b[i], b[rev[i]]);
for (int h = 1; h < len; h <<= 1)
for (int t = len / (h << 1), j = 0; j < len; j += (h << 1))
{
const int *wn = w;
int *bi = b + j, *bih = b + j + h;
for (int i = j; i < j + h; ++i)
{
const int _1 = *bi, _2 = mul(*bih, *wn);
*bi++ = inc(_1, _2);
*bih++ = dec(_1, _2);
wn += t;
}
}
if (w == omegaInv)
{
const int factor = mod - (mod - 1) / len;
for (int i = 0; i < len; ++i) b[i] = mul(b[i], factor);
}
}
inline void operator() (Poly &a, int op)
{
if (op == 1) operator()(a, omega);
if (op == -1) operator()(a, omegaInv);
}
} ntt;
struct Complex
{
long double x, y;
Complex (long double x = 0.0, long double y = 0.0) : x(x), y(y) {}
inline Complex conj() { return Complex(x, -y); }
};
inline Complex operator+ (Complex a, Complex b) { return Complex(a.x + b.x, a.y + b.y); }
inline Complex operator- (Complex a, Complex b) { return Complex(a.x - b.x, a.y - b.y); }
inline Complex operator* (Complex a, Complex b) { return Complex(a.x * b.x - a.y * b.y, a.y * b.x + a.x * b.y); }
inline Complex operator* (Complex a, long double b) { return Complex(a.x * b, a.y * b); }
inline Complex operator/ (Complex a, long double b) { return Complex(a.x / b, a.y / b); }
static const long double pi = acosl(-1.0L);
struct FFT
{
int rev[N], len, k;
Complex omega[N], omegaInv[N];
inline void init(int n)
{
int last_len = len;
k = 0, len = 1;
while (len <= n) ++k, len <<= 1;
if (len == last_len) return;
for (int i = 1; i < len; ++i) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (k - 1));
omega[0] = omegaInv[0] = 1;
Complex t(cosl(2.0L * pi / len), sinl(2.0L * pi / len));
for (int i = 1; i < len; ++i)
if (i & 32) omega[i] = omegaInv[len - i] = omega[i - 1] * t;
else omega[i] = omegaInv[len - i] = Complex(cosl(2.0L * pi * i / len), sinl(2.0L * pi * i / len));
}
inline void operator() (std::vector<Complex> &A, const Complex *w)
{
if (A.size() < len) A.resize(len);
for (int i = 0; i < len; ++i) if (i < rev[i]) std::swap(A[i], A[rev[i]]);
for (int h = 1; h < len; h <<= 1)
for (int t = len / (h * 2), j = 0; j < len; j += h * 2)
{
const Complex *wn = w;
for (int i = j; i < j + h; ++i)
{
const Complex _1 = A[i], _2 = A[i + h] * *wn;
A[i] = _1 + _2, A[i + h] = _1 - _2;
wn += t;
}
}
if (w == omegaInv)
{
for (int i = 0; i < len; ++i) A[i] = A[i] / len;
}
}
inline void operator() (std::vector<Complex> &A, int op)
{
if (op == 1) operator() (A, omega);
if (op == -1) operator() (A, omegaInv);
}
} fft;
inline Poly operator+(const Poly &P, const Poly &Q)
{
Poly R;
int deg = std::max(P.deg(), Q.deg());
for (int i = 0; i <= deg; ++i) R[i] = inc(P[i], Q[i]);
return R;
}
inline Poly operator+(const Poly &P, const int q)
{
Poly R = P.clone();
R[0] = inc(R[0], q);
return R;
}
inline Poly operator-(const Poly &P, const Poly &Q)
{
Poly R;
int deg = std::max(P.deg(), Q.deg());
for (int i = 0; i <= deg; ++i) R[i] = dec(P[i], Q[i]);
return R;
}
inline Poly operator-(const Poly &P, const int q)
{
Poly R = P.clone();
R[0] = dec(R[0], q);
return R;
}
inline Poly operator*(const Poly &_P, const Poly &_Q)
{
if (MODE == NTT_MODE)
{
Poly P = _P.clone(), Q = _Q.clone();
int deg = P.deg() + Q.deg();
Poly R;
if (P.deg() + Q.deg() <= 63)
{
R.redeg(P.deg() + Q.deg());
int *r = R.v.data();
const int *p = P.v.data(), *q = Q.v.data();
for (int i = 0; i <= P.deg(); ++i)
for (int j = 0; j <= Q.deg(); ++j)
r[i + j] = inc(r[i + j], mul(p[i], q[j]));
return R.slice(deg);
}
else
{
ntt.init(P.deg() + Q.deg() );
ntt(P, 1); ntt(Q, 1);
R.v.resize(ntt.len);
int *r = R.v.data();
const int *p = P.v.data(), *q = Q.v.data();
for (int i = 0; i < ntt.len; ++i) r[i] = mul(p[i], q[i]);
ntt(R, -1);
return R.slice(deg);
}
}
else
{
const int M = 1 << 15;
int n = _P.deg(), m = _Q.deg();
fft.init(n + m);
std::vector<Complex> P1, Q1, F1, F2;
P1.resize(n + 1); Q1.resize(m + 1);
for (int i = 0; i <= n; ++i) P1[i] = Complex(_P[i] & 32767, _P[i] >> 15);
for (int i = 0; i <= m; ++i) Q1[i] = Complex(_Q[i] & 32767, _Q[i] >> 15);
fft(P1, 1); fft(Q1, 1);
P1.push_back(P1[0]), Q1.push_back(Q1[0]);
F1.resize(fft.len), F2.resize(fft.len);
for (int i = 0; i < fft.len; ++i)
{
Complex p1 = (P1[i] + P1[fft.len - i].conj()) * 0.5,
p2 = (P1[i] - P1[fft.len - i].conj()) * Complex(0, -0.5),
q1 = (Q1[i] + Q1[fft.len - i].conj()) * 0.5,
q2 = (Q1[i] - Q1[fft.len - i].conj()) * Complex(0, -0.5);
F1[i] = Complex(p1 * q1 + Complex(0, 1) * p2 * q2);
F2[i] = Complex(p1 * q2 + p2 * q1);
}
fft(F1, -1); fft(F2, -1);
Poly result;
for (int i = 0; i <= n + m; ++i)
{
ll x1 = (ll)(F1[i].x + 0.5) % mod, x2 = (ll)(F1[i].y + 0.5) % mod, x3 = (ll)(F2[i].x + 0.5) % mod;
result[i] = (x1 + 1ll * M * M * x2 + 1ll * M * x3) % mod;
}
return result;
}
}
inline Poly PolyInv(const Poly &A)
{
Poly Ax, R;
int n = A.deg();
if (n == 0) return Poly({ mt.inv(A[0]) });
if (MODE == NTT_MODE)
{
R = PolyInv(A.slice(A.deg() >> 1));
ntt.init(A.deg() << 1);
Ax = A.clone();
ntt(Ax, 1); ntt(R, 1);
for (int i = 0; i < ntt.len; ++i) Ax[i] = dec(mul(Ax[i], R[i]), 1);
for (int i = 0; i < ntt.len; ++i) R[i] = mul(R[i], dec(1, Ax[i]));
ntt(R, -1);
R.redeg(n);
return R;
}
else
{
R = PolyInv(A.slice(n >> 1));
R.redeg(n);
Ax = A * R - 1;
Ax.redeg(n);
return (R - R * Ax).slice(n);
}
}
inline Poly Poly::inv() const
{
return PolyInv(*this).slice(deg());
}
inline Poly Poly::derivative() const
{
Poly R;
for (int i = 0; i < deg(); ++i) R[i] = mul(i + 1, operator[](i + 1));
return R;
}
inline Poly Poly::integration() const
{
Poly R;
for (int i = 1; i <= deg(); ++i) R[i] = mul(mt.inv(i), operator[](i - 1));
return R;
}
inline Poly Poly::ln() const
{
return (derivative() * inv()).integration().slice(deg());
}
inline Poly PolyExp(const Poly &A)
{
Poly Ax, Ay, R;
int n = A.deg();
if (n == 0) return Poly({1});
R = PolyExp(A.slice(n >> 1)).slice(n);
Ax = R.ln();
Ay = A.slice(n);
return R * (Ay + 1 - Ax);
}
inline Poly Poly::exp() const
{
return PolyExp(*this).slice(deg());
}
inline std::pair<Poly, Poly> PolyDiv(const Poly &F, const Poly &G)
{
Poly Fx, Gx, GrInv, Px, P, Q;
int n = F.deg(), m = G.deg();
Fx = F.clone(), Gx = G.clone();
Fx.reverse(); Gx.reverse(); Fx.redeg(n - m + 1);
Gx.redeg(std::max(m, n - m)); GrInv = Gx.inv();
P = Fx * GrInv;
P.redeg(n - m); P.reverse(); Gx = G.clone();
Q = Gx * P; Q.redeg(m - 1);
for (int i = 0; i <= m - 1; ++i) Q[i] = dec(F[i], Q[i]);
return std::make_pair(Q, P);
}
inline Poly PolySqrt(const Poly &A)
{
int n = A.deg();
if (n == 0)
{
assert(A[0] == 0 || A[0] == 1);
return Poly({A[0]});
}
Poly R = PolySqrt(A.slice(n >> 1));
R.redeg(n);
Poly H = R.inv(), K = (R * R).slice(n);
for (int i = 0; i <= H.deg(); ++i) H[i] = mul(H[i], inv2);
return (A + K) * H;
}
inline Poly Poly::sqrt() const
{
return PolySqrt(*this).slice(deg());
}
inline Poly operator%(const Poly &P, const Poly &Q) { return PolyDiv(P, Q).first; }
inline Poly operator/(const Poly &P, const Poly &Q) { return PolyDiv(P, Q).second; }
inline Poly Mul_T(const Poly &a, const Poly &b)
{
Poly R, A = a.clone(), B = b.clone();
if (A.deg() <= 100)
{
for (int i = a.deg(); i >= 0; --i)
for (int j = std::max(0, i - (a.deg() - b.deg())); j <= std::min(i, b.deg()); ++j)
R[i - j] = inc(R[i - j], mul(a[i], b[j]));
return R;
}
else
{
B.reverse();
ntt.init(A.deg());
ntt(A, 1); ntt(B, 1);
for (int i = 0; i < ntt.len; ++i) A[i] = mul(A[i], B[i]);
ntt(A, -1);
int c = 0;
for (int i = b.deg(); i <= a.deg(); ++i) R[c++] = A[i];
return R;
}
}
inline std::vector<int> Poly::evaluation(const std::vector<int> &vals) const
{
std::vector<Poly> T, F;
int m = vals.size();
int t = std::max(deg(), (int)vals.size() - 1);
ntt.init(t);
T.resize(t * 4); F.resize(t * 4);
std::function<void(int, int, int)> solve = [&](int o, int l, int r)
{
T[0].redeg(-1);
if (l == r) T[o] = Poly({1, dec(0, vals[l])});
else
{
const int mid = l + r >> 1;
solve(lc(o), l, mid); solve(rc(o), mid + 1, r);
T[o] = T[lc(o)] * T[rc(o)];
}
};
std::function<void(int, int, int, std::vector<int>&)> solve2 = [&](int o, int l, int r, std::vector<int> &ans)
{
if (l >= m) return;
if (l == r) ans.push_back(F[o][0]);
else
{
const int mid = l + r >> 1;
F[lc(o)] = Mul_T(F[o], T[rc(o)]);
F[rc(o)] = Mul_T(F[o], T[lc(o)]);
solve2(lc(o), l, mid, ans); solve2(rc(o), mid + 1, r, ans);
}
};
solve(1, 0, t);
Poly Q = T[1].inv();
Q.redeg(t);
Q.reverse();
Poly R = Q * *this;
for (int i = t; i <= R.deg(); ++i) F[1][i - t] = R[i];
F[1].redeg(t);
std::vector<int> ans;
solve2(1, 0, t, ans);
return ans;
}
inline void Poly::interpolation(const std::vector<std::pair<int, int> > &points)
{
int n = points.size();
std::vector<Poly> T(n << 2);
std::vector<int> vals;
for (auto v : points) vals.push_back(v.first);
std::function<void(int, int, int)> solve = [&](int o, int l, int r)
{
if (l == r) T[o] = Poly({ dec(0, vals[l]), 1 });
else
{
const int mid = l + r >> 1;
solve(lc(o), l, mid); solve(rc(o), mid + 1, r);
T[o] = T[lc(o)] * T[rc(o)];
}
};
solve(1, 0, n - 1);
Poly g = T[1], dg = g.derivative();
std::vector<int> ys = dg.evaluation(vals);
std::function<Poly(int, int, int)> solve2 = [&](int o, int l, int r)
{
if (l == r) return Poly({ mul(points[l].second, mt.inv(ys[l])) });
const int mid = l + r >> 1;
return solve2(lc(o), l, mid) * T[rc(o)] + solve2(rc(o), mid + 1, r) * T[lc(o)];
};
*this = solve2(1, 0, n - 1);
}
int main()
{
mt.init();
int n = read(); Poly P;
for (int i = 0; i < n; ++i) P[i] = read();
P.exp().print();
return 0;
}
详细
Test #1:
score: 20
Accepted
time: 113ms
memory: 241900kb
input:
100 0 158447743 737554986 671332600 489297184 754299210 115728600 816221630 819073359 691660913 910093246 562505672 355119917 385019894 611338034 123976316 122342952 82142434 796101450 994778874 575255638 493217967 652609142 662045597 783871340 470398790 241710709 754059035 534582325 836438174 957893067 584407346 640541600 410035922 84171732 175013006 606606840 773798688 469639368 144082552 758959232 657846445 877015573 456859086 388014168 518816564 674332059 227983790 428743727 438581021 222389...
output:
1 158447743 989903074 918187254 200068193 455062373 11196740 759336019 312075964 992242039 123230223 144998958 189062409 420150911 170942299 432890803 760087114 639614944 787205333 63667632 243571846 141993017 450288335 173318832 743144111 879389773 95666186 453410000 569486107 512729334 226210545 583843354 770244187 506859030 960348003 591955543 326668069 283535201 545276198 756666623 637645543 988390418 279027521 811851748 195335516 883324003 39642660 43553758 860245759 187849991 369088108 615...
result:
ok 100 numbers
Test #2:
score: 20
Accepted
time: 112ms
memory: 244032kb
input:
5000 0 354399910 26360255 630255958 717224815 366941345 333979504 905420494 38176634 475666562 611197455 433060682 509600868 845217181 520468365 529689763 431747498 192834976 685184103 287994809 273221518 522219732 427553800 10872482 525061651 448069946 183539744 610476003 840167561 241104955 404100586 905579642 619539314 759291945 841403216 335674561 812589295 739329439 436504205 457028593 882959179 173954181 530617359 285120636 874807613 623774085 659212492 947769439 351309346 244743499 453523...
output:
1 354399910 51676417 184411965 928033808 589971658 936383703 745898312 943454394 65252947 270867254 772620225 995104944 58521883 96491645 326592384 283913887 140742590 960115688 684602174 623426872 184484323 952879775 315489867 167038509 580362327 164714100 833258994 345402076 261957154 469710461 98909201 912220730 797482583 110446889 461158009 511291755 194079400 849976694 733749911 326177532 376934943 70169116 601713259 875738061 613122597 177648796 980516154 19290301 629815611 210848998 10036...
result:
ok 5000 numbers
Test #3:
score: 20
Accepted
time: 154ms
memory: 246252kb
input:
30000 0 147199510 293972908 780683378 633744119 800282266 162025013 919460711 939176222 298044997 277962122 729446209 455723129 756791462 84697115 579989768 945113433 549318980 229266945 869577376 103161009 960973464 440149102 836285074 687333626 638404974 184096947 370164754 454531549 142629528 150136518 257960790 158701904 511542041 393663496 771954923 878900233 618098281 645781345 282407187 177883451 71013292 201053861 290140489 414256579 859623839 225235471 541514087 973378894 661254664 9601...
output:
1 147199510 30930552 734023222 564008583 299902819 450980389 806779390 654937901 981162061 206882721 35851319 707998765 357594654 305814262 734562024 591099032 543969413 539432668 154163976 451201740 856569012 898961429 732819402 243444529 673245321 601964526 206333661 876679409 438174247 903706710 721924549 366525586 182013075 390789902 864037091 410595937 353024238 970691911 570639496 66536517 107591114 700244315 429693759 419045658 4401063 873683305 106667518 211342016 289811703 929820725 107...
result:
ok 30000 numbers
Test #4:
score: 20
Accepted
time: 287ms
memory: 253664kb
input:
100000 0 279349013 196667718 617497154 78288698 996674429 180463729 304956112 173800460 352061138 224505321 119706982 726737325 564797383 757014824 888433954 747100108 723246918 645172013 184990722 321964667 456686646 138153830 701558524 317746193 650472945 49496183 864461799 982372868 582778782 242264290 885892104 738219036 281176547 57656491 78806101 218302501 307656256 981707358 893325626 285028204 670805979 780203944 868002994 665180137 173048965 901701985 859037831 56668037 446632049 105548...
output:
1 279349013 426120005 205100346 421201310 474118168 879116053 749708347 23319122 872190753 903275287 797670709 327019687 707029564 46014243 838268797 28223150 48499086 927009654 52188573 200586020 4624185 827007182 201682326 552029133 820855946 97607062 601649418 37529652 24405665 116064030 620516317 954331876 448141495 376194952 97146001 288311515 992837065 548519462 188045151 853500007 152581028 435901883 135969796 482104252 307859632 112811323 903041365 525769409 402229514 778972652 345568114...
result:
ok 100000 numbers
Test #5:
score: 20
Accepted
time: 2575ms
memory: 340284kb
input:
1000000 0 204517192 162156394 729093416 352181074 335898409 357987855 386581690 26622360 437289663 34104646 938411413 659876244 293619518 291093969 909364118 179765868 89417259 632261731 375051702 493701794 771716785 682264158 329653513 86558030 9195128 957504298 22555222 384175297 128022431 595744458 181498790 672338926 479510752 420389346 652086132 134440599 263340995 500647786 721266545 21205425 522098385 546869280 418858420 804140401 347071725 717515538 26493457 742389665 501200675 718700801...
output:
1 204517192 619471860 517479130 453571099 756084155 250936574 733632267 123356262 736823877 36879005 134860159 91607107 898896915 410588432 269428255 936285724 807500080 148699607 694600424 104902381 245153045 814276600 610840817 459421157 797608659 275590448 967892574 251820609 688675003 675994534 799183221 807078890 630376087 672054870 317377125 864225720 411480601 228689924 428279368 644178736 797540609 244645218 88067648 156501744 496593476 469069796 200957333 685393397 327159366 90054383 80...
result:
ok 1000000 numbers