QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#778292#7923. Ferris WheeldanielzTL 1319ms98436kbC++204.5kb2024-11-24 13:53:132024-11-24 13:53:13

Judging History

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

  • [2024-11-24 13:53:13]
  • 评测
  • 测评结果:TL
  • 用时:1319ms
  • 内存:98436kb
  • [2024-11-24 13:53:13]
  • 提交

answer

#include <bits/stdc++.h>
using namespace std;
using namespace std;
using namespace std;
using ll = long long;
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) { v = (v * o.v) % M; return *this; }
    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; }
};
const int M = 998244353;
const int K = 23; // largest power of 2 that divides M - 1
// polynomial
using T = mint<M>;
struct F : vector<T> {
    inline static T w = mint<M>{3}.exp((M - 1) / (1 << K));
    inline static T i2 = mint<M>{2}.inv();
    // primitives
    F& resize(size_t sz) { return vector<T>::resize(__bit_ceil(sz)), *this; }
    F slice(size_t sz) const { F g = *this; return g.resize(sz), g; }
    F(int x) : vector<T>(1, x) { }
    F(initializer_list<T> l = {}) : vector<T>(l) {}
    // FFT
    F& fft(bool inv = false) { // inplace fft/ifft
        for (int _ = 0; (1 << _) < size(); _++) {
            int s = inv ? 1 << _ : size() >> 1 >> _; // stride
            assert(s < (1 << K));
            T dw = w.exp((1 << (K - 1)) / s);
            if (inv) dw = dw.inv();
            T W = 1;
            for (int i = 0; i < size(); i++) if (!(i & s)) {
                W = (i & (s - 1) ? W * dw : 1);
                T x = at(i), y = at(i | s);
                tie(at(i), at(i | s)) = inv ?
                    make_tuple((x + y * W) * i2, (x - y * W) * i2) :
                    make_tuple(x + y, (x - y) * W);
            }
        }
        return *this;
    }
    // data
    T& operator[](int i) {
        if (i >= size()) resize(i + 1);
        return at(i);
    }
    // cout override
    friend ostream& operator<<(ostream& os, F f) {
        for (mint<M> x : f) os << x << " ";
        return os;
    }
    // operations
    F& operator+=(const F &o) {
        for (int i = 0; i < min(size(), o.size()); i++) at(i) += o.at(i);
        return *this;
    }
    F operator+(const F &o) const { return F(*this) += o; }
    F operator*=(const F &o) {
        int n = 2 * max(size(), o.size());
        resize(n);
        F b = o.slice(n);
        fft(), b.fft();
        for (int i = 0; i < n; i++) at(i) *= b[i];
        return fft(true);
    }
    F operator*(const F &o) const { return F(*this) *= o; }
    F operator/=(const F &o) { return *this *= o.inv(); }
    F operator/(const F &o) const { return F(*this) /= o; }
    // inverse
    F inv() const {
        if (!at(0).v) throw logic_error("cannot invert polynomial with f(0) == 0");
        F g{at(0).inv()};
        for (int k = 2; k < size(); k <<= 1) {
            g *= ((slice(k) * g).resize(k) * -1 + 2);
            g.resize(k);
        }
        return g;
    }
};
using ll = long long;
const ll inf = 1e18;
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]; }
};
const int N = 6e6 + 1;
F 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;
    // gcd has to be either 2 * n or <= n
    for (int i = 1; 2 * i <= n; i++) {
        f[2 * i] = ctln(i - 1) * k * (k - 1).exp(i - 1);
        g[i * 2 + 1] = C.C(2 * i, i) * k * (k - 1).exp(i);
    }
    gf = (f / (f * -1 + 1) + 1).slice(n) * (g + 1); // [i] -> # of colorings for RBS + extra stuff of len i
    for (int i = 1; i <= 2 * n; i++) ++c[gcd(i, 2 * n)];
    for (int i = 1; i <= n; i++) gf[2 * n] += mint<M>{i} / (2 * n - i) * C.C(2 * n - i, n) * (k - 1).exp(n - i) * k.exp(i);
    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: 100
Accepted
time: 1310ms
memory: 97884kb

input:

3 2

output:

6

result:

ok single line: '6'

Test #2:

score: 0
Accepted
time: 1310ms
memory: 98436kb

input:

5 3

output:

372

result:

ok single line: '372'

Test #3:

score: 0
Accepted
time: 1319ms
memory: 98176kb

input:

2023 1126

output:

900119621

result:

ok single line: '900119621'

Test #4:

score: -100
Time Limit Exceeded

input:

2882880 2892778

output:


result: