QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#569606 | #9330. Series Sum | ucup-team004# | AC ✓ | 1472ms | 63748kb | C++20 | 16.3kb | 2024-09-17 01:22:49 | 2024-09-17 01:22:51 |
Judging History
answer
#include <bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
using u32 = unsigned;
template<class T>
constexpr T power(T a, i64 b) {
T res = 1;
for (; b; b /= 2, a *= a) {
if (b % 2) {
res *= a;
}
}
return res;
}
template<int P>
struct MInt {
int x;
constexpr MInt() : x{} {}
constexpr MInt(i64 x) : x{norm(x % getMod())} {}
static int Mod;
constexpr static int getMod() {
if (P > 0) {
return P;
} else {
return Mod;
}
}
constexpr static void setMod(int Mod_) {
Mod = Mod_;
}
constexpr int norm(int x) const {
if (x < 0) {
x += getMod();
}
if (x >= getMod()) {
x -= getMod();
}
return x;
}
constexpr int val() const {
return x;
}
explicit constexpr operator int() const {
return x;
}
constexpr MInt operator-() const {
MInt res;
res.x = norm(getMod() - x);
return res;
}
constexpr MInt inv() const {
assert(x != 0);
return power(*this, getMod() - 2);
}
constexpr MInt &operator*=(MInt rhs) & {
x = 1LL * x * rhs.x % getMod();
return *this;
}
constexpr MInt &operator+=(MInt rhs) & {
x = norm(x + rhs.x);
return *this;
}
constexpr MInt &operator-=(MInt rhs) & {
x = norm(x - rhs.x);
return *this;
}
constexpr MInt &operator/=(MInt rhs) & {
return *this *= rhs.inv();
}
friend constexpr MInt operator*(MInt lhs, MInt rhs) {
MInt res = lhs;
res *= rhs;
return res;
}
friend constexpr MInt operator+(MInt lhs, MInt rhs) {
MInt res = lhs;
res += rhs;
return res;
}
friend constexpr MInt operator-(MInt lhs, MInt rhs) {
MInt res = lhs;
res -= rhs;
return res;
}
friend constexpr MInt operator/(MInt lhs, MInt rhs) {
MInt res = lhs;
res /= rhs;
return res;
}
friend constexpr std::istream &operator>>(std::istream &is, MInt &a) {
i64 v;
is >> v;
a = MInt(v);
return is;
}
friend constexpr std::ostream &operator<<(std::ostream &os, const MInt &a) {
return os << a.val();
}
friend constexpr bool operator==(MInt lhs, MInt rhs) {
return lhs.val() == rhs.val();
}
friend constexpr bool operator!=(MInt lhs, MInt rhs) {
return lhs.val() != rhs.val();
}
};
template<>
int MInt<0>::Mod = 1;
template<int V, int P>
constexpr MInt<P> CInv = MInt<P>(V).inv();
constexpr int P = 998244353;
using Z = MInt<P>;
std::vector<int> rev;
template<int P>
std::vector<MInt<P>> roots{0, 1};
template<int P>
constexpr MInt<P> findPrimitiveRoot() {
MInt<P> i = 2;
int k = __builtin_ctz(P - 1);
while (true) {
if (power(i, (P - 1) / 2) != 1) {
break;
}
i += 1;
}
return power(i, (P - 1) >> k);
}
template<int P>
constexpr MInt<P> primitiveRoot = findPrimitiveRoot<P>();
template<>
constexpr MInt<998244353> primitiveRoot<998244353> {31};
template<int P>
constexpr void dft(std::vector<MInt<P>> &a) {
int n = a.size();
if (int(rev.size()) != n) {
int k = __builtin_ctz(n) - 1;
rev.resize(n);
for (int i = 0; i < n; i++) {
rev[i] = rev[i >> 1] >> 1 | (i & 1) << k;
}
}
for (int i = 0; i < n; i++) {
if (rev[i] < i) {
std::swap(a[i], a[rev[i]]);
}
}
if (roots<P>.size() < n) {
int k = __builtin_ctz(roots<P>.size());
roots<P>.resize(n);
while ((1 << k) < n) {
auto e = power(primitiveRoot<P>, 1 << (__builtin_ctz(P - 1) - k - 1));
for (int i = 1 << (k - 1); i < (1 << k); i++) {
roots<P>[2 * i] = roots<P>[i];
roots<P>[2 * i + 1] = roots<P>[i] * e;
}
k++;
}
}
for (int k = 1; k < n; k *= 2) {
for (int i = 0; i < n; i += 2 * k) {
for (int j = 0; j < k; j++) {
MInt<P> u = a[i + j];
MInt<P> v = a[i + j + k] * roots<P>[k + j];
a[i + j] = u + v;
a[i + j + k] = u - v;
}
}
}
}
template<int P>
constexpr void idft(std::vector<MInt<P>> &a) {
int n = a.size();
std::reverse(a.begin() + 1, a.end());
dft(a);
MInt<P> inv = (1 - P) / n;
for (int i = 0; i < n; i++) {
a[i] *= inv;
}
}
template<int P = 998244353>
struct Poly : public std::vector<MInt<P>> {
using Value = MInt<P>;
Poly() : std::vector<Value>() {}
explicit constexpr Poly(int n) : std::vector<Value>(n) {}
explicit constexpr Poly(const std::vector<Value> &a) : std::vector<Value>(a) {}
constexpr Poly(const std::initializer_list<Value> &a) : std::vector<Value>(a) {}
template<class InputIt, class = std::_RequireInputIter<InputIt>>
explicit constexpr Poly(InputIt first, InputIt last) : std::vector<Value>(first, last) {}
template<class F>
explicit constexpr Poly(int n, F f) : std::vector<Value>(n) {
for (int i = 0; i < n; i++) {
(*this)[i] = f(i);
}
}
constexpr Poly shift(int k) const {
if (k >= 0) {
auto b = *this;
b.insert(b.begin(), k, 0);
return b;
} else if (this->size() <= -k) {
return Poly();
} else {
return Poly(this->begin() + (-k), this->end());
}
}
constexpr Poly trunc(int k) const {
Poly f = *this;
f.resize(k);
return f;
}
constexpr friend Poly operator+(const Poly &a, const Poly &b) {
Poly res(std::max(a.size(), b.size()));
for (int i = 0; i < a.size(); i++) {
res[i] += a[i];
}
for (int i = 0; i < b.size(); i++) {
res[i] += b[i];
}
return res;
}
constexpr friend Poly operator-(const Poly &a, const Poly &b) {
Poly res(std::max(a.size(), b.size()));
for (int i = 0; i < a.size(); i++) {
res[i] += a[i];
}
for (int i = 0; i < b.size(); i++) {
res[i] -= b[i];
}
return res;
}
constexpr friend Poly operator-(const Poly &a) {
std::vector<Value> res(a.size());
for (int i = 0; i < int(res.size()); i++) {
res[i] = -a[i];
}
return Poly(res);
}
constexpr friend Poly operator*(Poly a, Poly b) {
if (a.size() == 0 || b.size() == 0) {
return Poly();
}
if (a.size() < b.size()) {
std::swap(a, b);
}
int n = 1, tot = a.size() + b.size() - 1;
while (n < tot) {
n *= 2;
}
if (((P - 1) & (n - 1)) != 0 || b.size() < 128) {
Poly c(a.size() + b.size() - 1);
for (int i = 0; i < a.size(); i++) {
for (int j = 0; j < b.size(); j++) {
c[i + j] += a[i] * b[j];
}
}
return c;
}
a.resize(n);
b.resize(n);
dft(a);
dft(b);
for (int i = 0; i < n; ++i) {
a[i] *= b[i];
}
idft(a);
a.resize(tot);
return a;
}
constexpr friend Poly operator*(Value a, Poly b) {
for (int i = 0; i < int(b.size()); i++) {
b[i] *= a;
}
return b;
}
constexpr friend Poly operator*(Poly a, Value b) {
for (int i = 0; i < int(a.size()); i++) {
a[i] *= b;
}
return a;
}
constexpr friend Poly operator/(Poly a, Value b) {
for (int i = 0; i < int(a.size()); i++) {
a[i] /= b;
}
return a;
}
constexpr Poly &operator+=(Poly b) {
return (*this) = (*this) + b;
}
constexpr Poly &operator-=(Poly b) {
return (*this) = (*this) - b;
}
constexpr Poly &operator*=(Poly b) {
return (*this) = (*this) * b;
}
constexpr Poly &operator*=(Value b) {
return (*this) = (*this) * b;
}
constexpr Poly &operator/=(Value b) {
return (*this) = (*this) / b;
}
constexpr Poly deriv() const {
if (this->empty()) {
return Poly();
}
Poly res(this->size() - 1);
for (int i = 0; i < this->size() - 1; ++i) {
res[i] = (i + 1) * (*this)[i + 1];
}
return res;
}
constexpr Poly integr() const {
Poly res(this->size() + 1);
for (int i = 0; i < this->size(); ++i) {
res[i + 1] = (*this)[i] / (i + 1);
}
return res;
}
constexpr Poly inv(int m) const {
Poly x{(*this)[0].inv()};
int k = 1;
while (k < m) {
k *= 2;
x.resize(2 * k);
Poly<P> y(2 * k);
for (int i = 0; i < k && i < this->size(); i++) {
y[i] = (*this)[i];
}
dft(x);
dft(y);
for (int i = 0; i < 2 * k; i++) {
x[i] = x[i] * (2 - y[i] * x[i]);
}
idft(x);
x.resize(k);
}
return x.trunc(m);
}
constexpr Poly log(int m) const {
return (deriv() * inv(m)).integr().trunc(m);
}
constexpr Poly exp(int m) const {
Poly x{1};
int k = 1;
while (k < m) {
k *= 2;
x = (x * (Poly{1} - x.log(k) + trunc(k))).trunc(k);
}
return x.trunc(m);
}
constexpr Poly pow(int k, int m) const {
int i = 0;
while (i < this->size() && (*this)[i] == 0) {
i++;
}
if (i == this->size() || 1LL * i * k >= m) {
return Poly(m);
}
Value v = (*this)[i];
auto f = shift(-i) * v.inv();
return (f.log(m - i * k) * k).exp(m - i * k).shift(i * k) * power(v, k);
}
constexpr Poly sqrt(int m) const {
Poly x{1};
int k = 1;
while (k < m) {
k *= 2;
x = (x + (trunc(k) * x.inv(k)).trunc(k)) * CInv<2, P>;
}
return x.trunc(m);
}
constexpr Poly mulT(Poly b) const {
if (b.size() == 0) {
return Poly();
}
int n = b.size();
std::reverse(b.begin(), b.end());
return ((*this) * b).shift(-(n - 1));
}
constexpr std::vector<Value> eval(std::vector<Value> x) const {
if (this->size() == 0) {
return std::vector<Value>(x.size(), 0);
}
const int n = std::max(x.size(), this->size());
std::vector<Poly> q(4 * n);
std::vector<Value> ans(x.size());
x.resize(n);
std::function<void(int, int, int)> build = [&](int p, int l, int r) {
if (r - l == 1) {
q[p] = Poly{1, -x[l]};
} else {
int m = (l + r) / 2;
build(2 * p, l, m);
build(2 * p + 1, m, r);
q[p] = q[2 * p] * q[2 * p + 1];
}
};
build(1, 0, n);
std::function<void(int, int, int, const Poly &)> work = [&](int p, int l, int r, const Poly &num) {
if (r - l == 1) {
if (l < int(ans.size())) {
ans[l] = num[0];
}
} else {
int m = (l + r) / 2;
work(2 * p, l, m, num.mulT(q[2 * p + 1]).trunc(m - l));
work(2 * p + 1, m, r, num.mulT(q[2 * p]).trunc(r - m));
}
};
work(1, 0, n, mulT(q[1].inv(n)));
return ans;
}
};
template<int P = 998244353>
Poly<P> berlekampMassey(const Poly<P> &s) {
Poly<P> c;
Poly<P> oldC;
int f = -1;
for (int i = 0; i < s.size(); i++) {
auto delta = s[i];
for (int j = 1; j <= c.size(); j++) {
delta -= c[j - 1] * s[i - j];
}
if (delta == 0) {
continue;
}
if (f == -1) {
c.resize(i + 1);
f = i;
} else {
auto d = oldC;
d *= -1;
d.insert(d.begin(), 1);
MInt<P> df1 = 0;
for (int j = 1; j <= d.size(); j++) {
df1 += d[j - 1] * s[f + 1 - j];
}
assert(df1 != 0);
auto coef = delta / df1;
d *= coef;
Poly<P> zeros(i - f - 1);
zeros.insert(zeros.end(), d.begin(), d.end());
d = zeros;
auto temp = c;
c += d;
if (i - temp.size() > f - oldC.size()) {
oldC = temp;
f = i;
}
}
}
c *= -1;
c.insert(c.begin(), 1);
return c;
}
template<int P = 998244353>
MInt<P> linearRecurrence(Poly<P> p, Poly<P> q, i64 n) {
int m = q.size() - 1;
while (n > 0) {
auto newq = q;
for (int i = 1; i <= m; i += 2) {
newq[i] *= -1;
}
auto newp = p * newq;
newq = q * newq;
for (int i = 0; i < m; i++) {
p[i] = newp[i * 2 + n % 2];
}
for (int i = 0; i <= m; i++) {
q[i] = newq[i * 2];
}
n /= 2;
}
return p[0] / q[0];
}
struct Comb {
int n;
std::vector<Z> _fac;
std::vector<Z> _invfac;
std::vector<Z> _inv;
Comb() : n{0}, _fac{1}, _invfac{1}, _inv{0} {}
Comb(int n) : Comb() {
init(n);
}
void init(int m) {
if (m <= n) return;
_fac.resize(m + 1);
_invfac.resize(m + 1);
_inv.resize(m + 1);
for (int i = n + 1; i <= m; i++) {
_fac[i] = _fac[i - 1] * i;
}
_invfac[m] = _fac[m].inv();
for (int i = m; i > n; i--) {
_invfac[i - 1] = _invfac[i] * i;
_inv[i] = _invfac[i] * _fac[i - 1];
}
n = m;
}
Z fac(int m) {
if (m > n) init(2 * m);
return _fac[m];
}
Z invfac(int m) {
if (m > n) init(2 * m);
return _invfac[m];
}
Z inv(int m) {
if (m > n) init(2 * m);
return _inv[m];
}
Z binom(int n, int m) {
if (n < m || m < 0) return 0;
return fac(n) * invfac(m) * invfac(n - m);
}
} comb;
Poly<P> get(int n) {
if (n == 1) {
return {0, 1};
}
if (n % 2 == 1) {
auto f = get(n - 1);
f.resize(n + 1);
for (int i = n - 1; i >= 0; i--) {
f[i + 1] += f[i];
f[i] *= -(n - 1);
}
return f;
}
auto f = get(n / 2);
std::vector<Z> pw(n / 2 + 1);
pw[0] = 1;
for (int i = 1; i <= n / 2; i++) {
pw[i] = pw[i - 1] * (-n / 2);
}
auto g = Poly<P>(n / 2 + 1,
[&](int i) {
return f[i] * comb.fac(i);
}).mulT(Poly<P>(n / 2 + 1,
[&](int i) {
return comb.invfac(i) * pw[i];
}));
for (int i = 0; i <= n / 2; i++) {
g[i] *= comb.invfac(i);
}
return f * g;
}
void solve() {
int k, p;
std::cin >> k >> p;
Poly<P> f(k * p + 1);
f[0] = 2;
for (int i = 0; i <= k * p; i++) {
f[i] -= comb.invfac(i);
}
f = f.inv(k * p + 1);
for (int i = 0; i <= k * p; i++) {
f[i] *= comb.fac(i) * 2;
}
Poly<P> g = get(k);
for (int i = 0; i <= k; i++) {
g[i] *= comb.invfac(k);
}
int n = 1;
while (n < k * p + 1) {
n *= 2;
}
g.resize(n);
dft(g);
for (int i = 0; i < n; i++) {
g[i] = power(g[i], p);
}
idft(g);
Z ans = 0;
for (int i = 0; i <= k * p; i++) {
ans += f[i] * g[i];
}
std::cout << ans << "\n";
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int t = 1;
std::cin >> t;
while (t--) {
solve();
}
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 3616kb
input:
3 2 3 1 10 9 6
output:
818 204495126 16726290
result:
ok 3 number(s): "818 204495126 16726290"
Test #2:
score: 0
Accepted
time: 0ms
memory: 3476kb
input:
3 10 1 1 3 1 2
output:
2 26 6
result:
ok 3 number(s): "2 26 6"
Test #3:
score: 0
Accepted
time: 695ms
memory: 3780kb
input:
2112 16 51 27 30 32 22 6 69 1 7 6 40 15 63 23 37 11 57 6 92 8 62 5 50 11 76 1 57 99 8 2 90 35 10 13 54 6 33 8 70 14 48 12 63 7 99 85 7 14 60 7 78 22 22 1 53 6 61 2 67 8 68 5 67 7 57 8 79 11 29 15 44 8 62 19 39 9 71 3 65 3 83 6 16 11 86 7 25 124 6 1 21 5 76 17 35 14 29 1 55 67 13 987 1 8 27 4 99 8 19...
output:
958728366 182850046 337462356 238321759 94586 688819126 880558546 673294800 592760052 772846256 555807947 834237048 258386591 443217990 83210442 741605708 687991731 380324156 884202426 190172937 130140451 931313604 659396498 344165836 434542961 111646504 6836992 571531367 631528990 880394933 1976309...
result:
ok 2112 numbers
Test #4:
score: 0
Accepted
time: 1400ms
memory: 29128kb
input:
6 1 164257 7 10955 1 30358 1 198674 1 206507 1 323519
output:
450748134 285759990 479497879 856048370 75480834 220335166
result:
ok 6 numbers
Test #5:
score: 0
Accepted
time: 1472ms
memory: 62952kb
input:
4 62 12597 13 15082 2 11295 1 330
output:
134578883 817592796 66930551 383110659
result:
ok 4 number(s): "134578883 817592796 66930551 383110659"
Test #6:
score: 0
Accepted
time: 573ms
memory: 3868kb
input:
1009 31 32 25 40 41 24 500 2 29 34 38 26 38 26 90 11 200 5 71 14 50 20 34 29 47 21 125 8 111 9 37 27 142 7 45 22 125 8 27 36 58 17 27 36 35 28 28 35 43 23 125 8 333 3 32 31 71 14 25 39 100 10 35 28 27 36 47 21 27 37 66 15 47 21 25 40 37 27 34 29 45 22 35 28 66 15 333 3 50 20 25 39 25 39 26 38 76 13 ...
output:
871402622 419577502 603695744 784359155 759347810 51557094 51557094 712633402 954410959 616922676 816335450 256771489 866916495 760989591 859187268 459975997 550880541 525468303 760989591 277034910 243040669 277034910 631662375 200080307 141253289 760989591 775322262 996562074 616922676 86443311 524...
result:
ok 1009 numbers
Test #7:
score: 0
Accepted
time: 1054ms
memory: 4264kb
input:
208 139 31 117 45 41 41 267 35 82 16 3 45 181 41 1219 8 31 44 1528 5 235 4 222 10 269 26 827 2 870 7 16 23 263 25 11 26 660 15 129 41 141 11 64 36 100 49 122 50 276 27 44 11 128 24 217 37 335 14 24 49 237 39 418 18 48 35 94 33 375 16 4 47 121 39 95 12 858 7 304 31 370 21 182 33 194 15 55 6 202 13 24...
output:
851150545 222205624 161298067 690708886 622565881 900621090 661760377 251742611 60893316 648664643 49553591 112014667 919771321 587648714 771905571 833478149 713320155 677714356 137765434 3585171 981954406 488903479 513181593 874511965 16170849 442603529 950708093 985481603 369032829 887191778 69043...
result:
ok 208 numbers
Test #8:
score: 0
Accepted
time: 1186ms
memory: 63748kb
input:
1 1000 1000
output:
783050993
result:
ok 1 number(s): "783050993"
Test #9:
score: 0
Accepted
time: 122ms
memory: 4144kb
input:
10 100 100 99 101 98 102 97 103 96 104 101 99 102 98 103 97 104 96 105 95
output:
745474847 348955190 781334174 938153402 358565847 695815461 196183578 379968206 129529953 29572094
result:
ok 10 numbers
Test #10:
score: 0
Accepted
time: 0ms
memory: 3780kb
input:
6 3 2 4 4 3 3 3 5 5 3 4 5
output:
126 124014359 32162 328827205 64386506 567277979
result:
ok 6 numbers
Test #11:
score: 0
Accepted
time: 1244ms
memory: 10300kb
input:
10 100 1000 1000 100 250 400 400 250 25000 4 5 20000 10 10000 10000 10 20000 5 4 25000
output:
354756979 228119416 829496936 168882209 168334375 302715191 745862435 202616186 375396996 520541595
result:
ok 10 numbers
Test #12:
score: 0
Accepted
time: 1ms
memory: 3796kb
input:
10 7 7 5 8 10 4 13 2 2 15 3 9 8 8 6 9 5 3 4 10
output:
629286899 91930612 465722397 823378532 871380528 417689043 815208695 887739621 64386506 566247517
result:
ok 10 numbers