QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#771804 | #7923. Ferris Wheel | danielz | ML | 0ms | 0kb | C++20 | 6.6kb | 2024-11-22 15:47:14 | 2024-11-22 15:47:19 |
answer
#include <bits/stdc++.h>
using ll = long long;
const ll inf = 1e18;
using namespace std;
template <int M>
struct mint {
ll v = 0;
mint() {}
mint(ll v) { this->v = (v % M + M) % M; }
mint operator+(const mint &o) const { return v + o.v; }
mint& operator+=(const mint& o) { v = (v + o.v) % M; return *this; }
mint operator*(const mint &o) const { return v * o.v; }
mint operator-(const mint &o) const { return v - o.v; }
mint& operator-=(const mint& o) { mint t = v - o.v; v = t.v; return *this; }
mint exp(int y) const { mint r = 1, x = v; for (y <<= 1; y >>= 1; x = x * x) if (y & 1) r = r * x; return r; }
mint operator/(mint o) { return *this * o.inv(); }
mint inv() const { assert(v); return exp(M - 2); }
friend istream& operator>>(istream& s, mint& v) { s >> v.v; return s; }
friend ostream& operator<<(ostream& s, const mint& v) { s << v.v; return s; }
};
using namespace std;
const int M = 998244353;
const mint<M> i2 = mint<M>(2).inv(); // self-explanatory
// make sure N is a power of two!
template <int N>
struct F {
inline static mint<M> w = mint<M>(3).exp((M - 1) / (N << 1));
inline static mint<M> iw = w.inv();
inline static mint<M> p[N << 1]{}, ip[N << 1]{}; // powers and inverse powers
mint<M> a[N << 1]{}, f[N << 1]{}; // a is actual array, f is for fft values
int n = 1; // should always be power of two
F(initializer_list<mint<M> > l = {}, bool t = false) {
assert(l.size() <= N && __builtin_popcount(N) == 1);
int i = 0; for (mint<M> x : l) a[i++] = x;
while (n < l.size()) n <<= 1;
}
F& rsz(int k, bool e = false) { assert(k <= (N << 1));
if (e) for (int i = k; i < n; i++) a[i] = 0; n = k; return *this;
}
F slice(int k, bool e = false) { assert(k <= (N << 1));
return F(*this).rsz(k, e);
}
F& fft(int n = 0, bool inv = false) {
if (!n) n = this->n;
if (!p[0].v) { // initialize array of powers if not done yet
p[0] = 1; for (int i = 1; i < (N << 1); i++) p[i] = p[i - 1] * w;
ip[0] = 1; for (int i = 1; i < (N << 1); i++) ip[i] = ip[i - 1] * iw;
}
if (!inv) for (int i = 0; i < n; i++) f[i] = i < this->n ? a[i] : 0;
for (int _ = 0; (1 << _) < n; _++) {
int s = inv ? 1 << _ : n >> 1 >> _; // stride
for (int i = 0; i < n; i++) if (!(i & s)) {
mint<M> W = (inv ? ip : p)[N / s * (i & (s - 1))];
mint<M> x = f[i], y = f[i | s];
if (inv) f[i] = (x + y * W) * i2, f[i | s] = (x - y * W) * i2;
else f[i] = x + y, f[i | s] = (x - y) * W;
}
}
if (inv) for (int i = 0; i < n; i++) a[i] = f[i];
return *this;
}
F& ifft(int n = 0) { if (!n) n = this->n; return fft(n, true); }
mint<M>& operator[](int i) { while (i >= n) n <<= 1; return a[i]; }
// pointwise multiplication of fft coeffs
F& dot(F &g) { for (int i = 0; i < n; i++) f[i] = f[i] * g.f[i]; return *this; }
// right shift (multiply by x^k)
F& operator>>=(int k) { for (int i = n; i --> 0; ) a[i] = (i < k ? 0 : a[i - k]); return *this; }
// left shift (divide by x^k)
F& operator<<=(int k) { for (int i = 0; i < n; i++) a[i] = (i + k < n ? a[i + k] : 0); return *this; }
// multiplication by scalar
F& operator*= (const mint<M> v) { for (int i = 0; i < n; i++) a[i] = a[i] * v; return *this; }
F operator* (const mint<M> v) {
return F(*this) *= v;
}
// addition by scalar
F& operator+= (const mint<M> &v) { a[0] = a[0] + v; return *this; }
F operator+ (const mint<M> &v) {
return F(*this) += v;
}
// adding two polynomials
F& operator+= (F o) { for (int i = 0; i < min(n, o.n); i++) a[i] = a[i] + o[i]; return *this; }
F operator+ (F o) {
return F(*this) += o;
}
// convolution
F& operator*= (F o) {
int k = max(n, o.n) << 1; assert(k <= (N << 1));
return fft(k).rsz(k).dot(o.fft(k)).ifft();
}
F operator* (F o) {
return F(*this) *= o;
}
friend ostream& operator<<(ostream& s, F f) {
for (int i = 0; i < f.n; i++) cout << f[i] << " ";
return s;
}
// multiplicative inverse (mod x^N)
F inv() {
if (!a[0].v) throw logic_error("cannot invert polynomial with f(0) == 0");
F g{a[0].inv()};
int n = this->n;
for (int k = 2; k <= n; k <<= 1) {
g *= (slice(k) * g).slice(k) * -1 + 2;
g.slice(k);
}
return g;
}
F operator/(F f) { F g = f.inv(); return *this * g; }
// derivative
F d() {
F r;
for (int i = 0; i < n - 1; i++) r[i] = mint<M>(i + 1) * a[i + 1];
r[n] = 0;
return r.slice(n);
}
// integral
F i() {
F r;
for (int i = n; i --> 1; ) r[i] = a[i - 1] / i;
r[0] = 0;
return r.slice(n);
}
F ln() { F g = inv(); return (g * d()).slice(n).i(); }
F exp() {
if (a[0].v) throw logic_error("f(0) must be 0 for e^f to exist");
F g = F{1};
int n = this->n;
for (int k = 2; k <= n; k <<= 1) {
g.slice(k);
F h = g.ln() * -1;
g *= slice(k) + h + 1;
}
return g;
}
F operator^(int x) {
F f = *this;
int i = 0; while (i < n && !f[i].v) i++;
if (i == n) return x ? F{0} : F{1};
f <<= i;
mint<M> a = f[0]; f *= a.inv();
F g = f.ln() * x;
F h = g.exp() * a.exp(x);
return h >>= (min(x, N) * i);
}
};
using namespace std;
template <int A, int M>
struct Combo {
mint<M> F[A], F_i[A];
Combo() { F[0] = F_i[0] = 1; for (int i = 1; i < A; i++) F_i[i] = (F[i] = F[i - 1] * i).inv(); }
mint<M> C(int n, int k) { return n < k ? 0 : F[n] * F_i[n - k] * F_i[k]; }
};
using namespace std;
const int N = 1 << 23;
F<N> f, g, gf;
Combo<N, M> C;
mint<M> ctln(int n) { return C.C(2 * n, n) / (n + 1); }
int c[N];
int main() {
int n; mint<M> k; cin >> n >> k;
g[1] = k;
for (int i = 1; i <= n; i++) {
f[2 * i] = ctln(i - 1) * k * (k - 1).exp(i - 1);
g[i * 2 + 1] = C.C(i * 2, i) * k * (k - 1).exp(i);
}
gf = (f / (f * -1 + 1) + 1) * (g + 1); // [i] -> # of colorings for RBS of len i
// gf2 = gf1 * g; // [i] -> # of colorings for RBS + potentially incomplete section of len i
for (int i = 1; i <= 2 * n; i++) ++c[gcd(i, 2 * n)];
mint<M> r = 0;
for (int i = 1; i <= 2 * n; i++) {
r += gf[i] * c[i];
}
cout << r / (2 * n) << endl;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 0
Memory Limit Exceeded
input:
3 2