QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#771804#7923. Ferris WheeldanielzML 0ms0kbC++206.6kb2024-11-22 15:47:142024-11-22 15:47:19

Judging History

你现在查看的是最新测评结果

  • [2024-11-22 15:47:19]
  • 评测
  • 测评结果:ML
  • 用时:0ms
  • 内存:0kb
  • [2024-11-22 15:47:14]
  • 提交

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;
}

详细

Test #1:

score: 0
Memory Limit Exceeded

input:

3 2

output:


result: