编号 题目 状态 分数 总时间 内存 代码 / 答案文件 提交者 提交时间
#4245 #1005. 计算机网络 Accepted 100 1275 ms 6488 K C++ 17 / 20.2 K admin 2023-09-24 11:07:58
显示原始代码
#include <iostream>
#include <random>
#include <cstring>
#include <vector>
#include <algorithm>
#include <assert.h>
#include <chrono>
using namespace std;
typedef unsigned int ui;
typedef unsigned long long ll;
#define all(x) (x).begin(), (x).end()

namespace NTT  //禁止混用三模与普通 NTT
{
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
#define all(x) (x).begin(), (x).end()

const int N = 1 << 21;  //务必修改
//#define MTT
//#define CRT
typedef unsigned int ui;
typedef unsigned long long ll;
const ui g = 3, f = 1u << 31, I = 86'583'718;  // g^((p-1)/4)
#ifndef MTT
const ui p = 998244353;
ui w[N];
#else
const ui p = 1e9 + 7;
const ui p1 = 469'762'049, p2 = 998'244'353, p3 = 1'004'535'809;  //三模,原根都是 3,非常好
const ui inv_p1 = 554'580'198, inv_p12 = 395'249'030;  //三模,1 关于 2 逆,1*2 关于 3 逆,1*2 mod 3
ui w1[N], w2[N], w3[N];                                //三模
#endif
ui r[N];
ui inv[N], fac[N], ifac[N], W;  // W for mosqrt
ui ksm(ui x, ui y) {
    ui r = 1;
    while (y) {
        if (y & 1)
            r = (ll)r * x % p;
        x = (ll)x * x % p;
        y >>= 1;
    }
    return r;
}
#ifdef MTT
#ifdef CRT
ui ksm1(ui x, ui y) {
    ui r = 1;
    while (y) {
        if (y & 1)
            r = (ll)r * x % p1;
        x = (ll)x * x % p1;
        y >>= 1;
    }
    return r;
}
ui ksm2(ui x, ui y) {
    ui r = 1;
    while (y) {
        if (y & 1)
            r = (ll)r * x % p2;
        x = (ll)x * x % p2;
        y >>= 1;
    }
    return r;
}
ui ksm3(ui x, ui y) {
    ui r = 1;
    while (y) {
        if (y & 1)
            r = (ll)r * x % p3;
        x = (ll)x * x % p3;
        y >>= 1;
    }
    return r;
}
#endif
#endif
vector<ui> getinvs(vector<ui> a) {
    static ui l[N], r[N];
    int n = a.size(), i;
    if (n <= 2) {
        for (i = 0; i < n; i++) a[i] = ksm(a[i], p - 2);
        return a;
    }
    l[0] = a[0];
    r[n - 1] = a[n - 1];
    for (i = 1; i < n; i++) l[i] = (ll)l[i - 1] * a[i] % p;
    for (i = n - 2; i; i--) r[i] = (ll)r[i + 1] * a[i] % p;
    ui x = ksm(l[n - 1], p - 2);
    a[0] = (ll)x * r[1] % p;
    a[n - 1] = (ll)x * l[n - 2] % p;
    for (i = 1; i < n - 1; i++) a[i] = (ll)x * l[i - 1] % p * r[i + 1] % p;
    return a;
}
struct P {
    ui x, y;
    P(ui a = 0, ui b = 0) : x(a), y(b) {}
    P operator*(P &a) { return P(((ll)x * a.x + (ll)y * a.y % p * W) % p, ((ll)x * a.y + (ll)y * a.x) % p); }
};
ui ksm(P x, ui y) {
    P r(1, 0);
    while (y) {
        if (y & 1)
            r = r * x;
        x = x * x;
        y >>= 1;
    }
    return r.x;
}
int mosqrt(ui x) {
    if (x == 0)
        return 0;
    if (ksm(x, p - 1 >> 1) != 1) {
        cerr << "No mosqrt" << endl;
        exit(0);
    }
    ui y;
    do y = rnd() % p;
    while (ksm(W = ((ll)y * y % p + p - x) % p, p - 1 >> 1) <= 1);  // not for p=2
    y = ksm(P(y, 1), p + 1 >> 1);
    return y * 2 < p ? y : p - y;
}
#ifdef MTT
#ifdef CRT
void init(ui n) {
    static int pre = 0;
    if (pre == n)
        return;
    ui b = __builtin_ctz(n) - 1, i, j, k, l, wn;
    for (i = 1; i < n; i++) r[i] = r[i >> 1] >> 1 | (i & 1) << b;
    ++b;
    if (pre < n) {
        for (j = k = 1; j < n; j = l, k++) {
            l = j << 1;
            wn = ksm1(g, p1 - 1 >> k);
            w1[j] = 1;
            for (i = j + 1; i < l; i++) w1[i] = (ll)w1[i - 1] * wn % p1;
        }
        for (j = k = 1; j < n; j = l, k++) {
            l = j << 1;
            wn = ksm2(g, p2 - 1 >> k);
            w2[j] = 1;
            for (i = j + 1; i < l; i++) w2[i] = (ll)w2[i - 1] * wn % p2;
        }
        for (j = k = 1; j < n; j = l, k++) {
            l = j << 1;
            wn = ksm3(g, p3 - 1 >> k);
            w3[j] = 1;
            for (i = j + 1; i < l; i++) w3[i] = (ll)w3[i - 1] * wn % p3;
        }
    }
    pre = n;
}
#endif
#else
void init(ui n) {
    static int pre = 0;
    if (pre == n)
        return;
    ui b = __builtin_ctz(n) - 1, i, j, k, l, wn;
    for (i = 1; i < n; i++) r[i] = r[i >> 1] >> 1 | (i & 1) << b;
    ++b;
    if (pre < n) {
        for (j = k = 1; j < n; j = l, k++) {
            l = j << 1;
            wn = ksm(g, p - 1 >> k);
            w[j] = 1;
            for (i = j + 1; i < l; i++) w[i] = (ll)w[i - 1] * wn % p;
        }
    }
    pre = n;
}
#endif
ui cal(ui x) { return 1u << 32 - __builtin_clz(max(x, 2u) - 1); }
void getinv(int n) {
    static int pre = 0;
    if (!pre)
        pre = inv[1] = 1;
    if (n <= pre)
        return;
    for (ui i = pre + 1, j; i <= n; i++) {
        j = p / i;
        inv[i] = (ll)(p - j) * inv[p - i * j] % p;
    }
    pre = n;
}
void getfac(int n) {
    static int pre = -1;
    if (pre == -1)
        pre = 0, ifac[0] = fac[0] = 1;
    if (n <= pre)
        return;
    getinv(n);
    for (ui i = pre + 1, j; i <= n; i++)
        fac[i] = (ll)fac[i - 1] * i % p, ifac[i] = (ll)ifac[i - 1] * inv[i] % p;
    pre = n;
}
struct Q {
    vector<ui> a;
    ui *pt() { return a.data(); }
    Q(ui x = 2) {
        x = cal(x);
        a.resize(x);
    }
    ui fx(ui x) {
        ui r = 0;
        int i;
        for (i = a.size() - 1; i >= 0 && !a[i]; i--)
            ;
        for (; i >= 0; i--) r = ((ll)r * x + a[i]) % p;
        return r;
    }
#ifdef MTT
#ifdef CRT
    void dft1(int o = 0) {
        ui n = a.size(), i, j, k, x, y, *f, *g, *wn, *A = a.data();
        init(n);
        for (i = 1; i < n; i++)
            if (i < r[i])
                swap(A[i], A[r[i]]);
        for (k = 1; k < n; k <<= 1) {
            wn = w1 + k;
            for (i = 0; i < n; i += k << 1) {
                f = A + i;
                g = A + i + k;
                for (j = 0; j < k; j++) {
                    x = f[j];
                    y = (ll)g[j] * wn[j] % p1;
                    if (x + y >= p1)
                        f[j] = x + y - p1;
                    else
                        f[j] = x + y;
                    if (x < y)
                        g[j] = x - y + p1;
                    else
                        g[j] = x - y;
                }
            }
        }
        if (o) {
            x = ksm1(n, p1 - 2);
            for (i = 0; i < n; i++) A[i] = (ll)A[i] * x % p1;
            reverse(A + 1, A + n);
        }
    }
    void dft2(int o = 0) {
        ui n = a.size(), i, j, k, x, y, *f, *g, *wn, *A = a.data();
        init(n);
        for (i = 1; i < n; i++)
            if (i < r[i])
                swap(A[i], A[r[i]]);
        for (k = 1; k < n; k <<= 1) {
            wn = w2 + k;
            for (i = 0; i < n; i += k << 1) {
                f = A + i;
                g = A + i + k;
                for (j = 0; j < k; j++) {
                    x = f[j];
                    y = (ll)g[j] * wn[j] % p2;
                    if (x + y >= p2)
                        f[j] = x + y - p2;
                    else
                        f[j] = x + y;
                    if (x < y)
                        g[j] = x - y + p2;
                    else
                        g[j] = x - y;
                }
            }
        }
        if (o) {
            x = ksm2(n, p2 - 2);
            for (i = 0; i < n; i++) A[i] = (ll)A[i] * x % p2;
            reverse(A + 1, A + n);
        }
    }
    void dft3(int o = 0) {
        ui n = a.size(), i, j, k, x, y, *f, *g, *wn, *A = a.data();
        init(n);
        for (i = 1; i < n; i++)
            if (i < r[i])
                swap(A[i], A[r[i]]);
        for (k = 1; k < n; k <<= 1) {
            wn = w3 + k;
            for (i = 0; i < n; i += k << 1) {
                f = A + i;
                g = A + i + k;
                for (j = 0; j < k; j++) {
                    x = f[j];
                    y = (ll)g[j] * wn[j] % p3;
                    if (x + y >= p3)
                        f[j] = x + y - p3;
                    else
                        f[j] = x + y;
                    if (x < y)
                        g[j] = x - y + p3;
                    else
                        g[j] = x - y;
                }
            }
        }
        if (o) {
            x = ksm3(n, p3 - 2);
            for (i = 0; i < n; i++) A[i] = (ll)A[i] * x % p3;
            reverse(A + 1, A + n);
        }
    }
#endif
#else
    void dft(int o = 0) {
        ui n = a.size(), i, j, k, x, y, *f, *g, *wn, *A = pt();
        init(n);
        for (i = 1; i < n; i++)
            if (i < r[i])
                swap(A[i], A[r[i]]);
        for (k = 1; k < n; k <<= 1) {
            wn = w + k;
            for (i = 0; i < n; i += k << 1) {
                f = A + i;
                g = A + i + k;
                for (j = 0; j < k; j++) {
                    x = f[j];
                    y = (ll)g[j] * wn[j] % p;
                    if (x + y >= p)
                        f[j] = x + y - p;
                    else
                        f[j] = x + y;
                    if (x < y)
                        g[j] = x - y + p;
                    else
                        g[j] = x - y;
                }
            }
        }
        if (o) {
            getinv(n);
            x = inv[n];
            for (i = 0; i < n; i++) A[i] = (ll)A[i] * x % p;
            reverse(A + 1, A + n);
        }
    }
    void hf_dft(int o = 0) {
        ui n = a.size() >> 1, i, j, k, x, y, *f, *g, *wn, *A = pt();
        init(n);
        for (i = 1; i < n; i++)
            if (i < r[i])
                swap(A[i], A[r[i]]);
        for (k = 1; k < n; k <<= 1) {
            wn = w + k;
            for (i = 0; i < n; i += k << 1) {
                f = A + i;
                g = A + i + k;
                for (j = 0; j < k; j++) {
                    x = f[j];
                    y = (ll)g[j] * wn[j] % p;
                    if (x + y >= p)
                        f[j] = x + y - p;
                    else
                        f[j] = x + y;
                    if (x < y)
                        g[j] = x - y + p;
                    else
                        g[j] = x - y;
                }
            }
        }
        if (o) {
            getinv(n);
            x = inv[n];
            for (i = 0; i < n; i++) A[i] = (ll)A[i] * x % p;
            reverse(A + 1, A + n);
        }
    }
#endif
    Q dao() {
        ui n = a.size();
        Q r(n);
        for (ui i = 1; i < n; i++) r.a[i - 1] = (ll)a[i] * i % p;
        return r;
    }
    Q ji() {
        ui n = a.size();
        getinv(n - 1);
        Q r(n);
        for (ui i = 1; i < n; i++) r.a[i] = (ll)a[i - 1] * inv[i] % p;
        return r;
    }
    Q operator-() const {
        Q r = *this;
        for (ui &x : r.a)
            if (x)
                x = p - x;
        return r;
    }
    Q operator+(ui x) const {
        Q r = *this;
        r += x;
        return r;
    }
    Q &operator+=(ui x) {
        if ((a[0] += x) >= p)
            a[0] -= p;
        return *this;
    }
    Q operator-(ui x) const {
        Q r = *this;
        r -= x;
        return r;
    }
    Q &operator-=(ui x) {
        if (a[0] < x)
            a[0] = a[0] + p - x;
        else
            a[0] -= x;
        return *this;
    }
    Q operator*(ui k) const {
        Q r = *this;
        r *= k;
        return r;
    }
    Q &operator*=(ui k) {
        for (ui &x : a) x = (ll)x * k % p;
        return *this;
    }
    Q operator+(Q f) const {
        f += *this;
        return f;
    }
    Q &operator+=(const Q &f) {
        ui n = f.a.size();
        if (a.size() < n)
            a.resize(n);
        for (ui i = 0; i < n; i++)
            if ((a[i] += f.a[i]) >= p)
                a[i] -= p;
        return *this;
    }
    Q operator-(Q f) const {
        Q r = *this;
        r -= f;
        return r;
    }
    Q &operator-=(const Q &f) {
        ui n = f.a.size();
        if (a.size() < n)
            a.resize(n);
        for (ui i = 0; i < n; i++)
            if (a[i] < f.a[i])
                a[i] += p - f.a[i];
            else
                a[i] -= f.a[i];
        return *this;
    }
    Q operator*(Q f) const {
        f *= *this;
        return f;
    }
#ifdef MTT
#ifdef CRT
    void operator*=(Q g3) {
        Q f, g1, g2;
        g1 = g2 = g3;
        assert(a.size() == g3.a.size());
        ui n = a.size() << 1, i;
        ll x;
        a.resize(n);
        g1.a.resize(n);
        g2.a.resize(n);
        g3.a.resize(n);
        g1.dft1();
        g2.dft2();
        g3.dft3();
        f = *this;
        f.dft1();
        for (i = 0; i < n; i++) g1.a[i] = (ll)g1.a[i] * f.a[i] % p1;
        g1.dft1(1);
        f = *this;
        f.dft2();
        for (i = 0; i < n; i++) g2.a[i] = (ll)g2.a[i] * f.a[i] % p2;
        g2.dft2(1);
        f = *this;
        f.dft3();
        for (i = 0; i < n; i++) g3.a[i] = (ll)g3.a[i] * f.a[i] % p3;
        g3.dft3(1);
        a.resize(n >>= 1);
        ui _p12 = (ll)p1 * p2 % p;
        for (i = 0; i < n; i++) {
            x = (ll)(g2.a[i] + p2 - g1.a[i]) * inv_p1 % p2 * p1 + g1.a[i];
            a[i] = ((x + p3 - g3.a[i]) % p3 * (p3 - inv_p12) % p3 * _p12 + x) % p;
        }
    }
#else
    void operator*=(const Q &g) {
        ui n = a.size(), m = (1 << 15) - 1, i;
        assert(n == g.a.size());
        n <<= 1;
        foly a0(n), a1(n), b0(n), b1(n), u(n), v(n);
        n >>= 1;
        for (i = 0; i < n; i++) a0.a[i].x = a[i] >> 15, a1.a[i].x = a[i] & m;
        for (i = 0; i < n; i++) b0.a[i].x = g.a[i] >> 15, b1.a[i].x = g.a[i] & m;
        ddt(a0, a1);
        ddt(b0, b1);
        n <<= 1;
        for (i = 0; i < n; i++) {
            u.a[i] = a0.a[i] * b0.a[i] + FFT::I * a1.a[i] * b0.a[i];
            v.a[i] = a0.a[i] * b1.a[i] + FFT::I * a1.a[i] * b1.a[i];
        }
        u.dft(1);
        v.dft(1);
        n >>= 1;
        a.resize(n);
        for (i = 0; i < n; i++)
            a[i] =
                ((((ll)dtol(u.a[i].x) << 15) % p + dtol(u.a[i].y) + dtol(v.a[i].x) << 15) + dtol(v.a[i].y)) %
                p;
    }
    void operator|=(const Q &g) {
        ui n = cal(a.size() + g.a.size() - 1), m = (1 << 15) - 1, i;
        foly a0(n), a1(n), b0(n), b1(n), u(n), v(n);
        for (i = 0; i < a.size(); i++) a0.a[i].x = a[i] >> 15, a1.a[i].x = a[i] & m;
        for (i = 0; i < g.a.size(); i++) b0.a[i].x = g.a[i] >> 15, b1.a[i].x = g.a[i] & m;
        ddt(a0, a1);
        ddt(b0, b1);
        for (i = 0; i < n; i++) {
            u.a[i] = a0.a[i] * b0.a[i] + FFT::I * a1.a[i] * b0.a[i];
            v.a[i] = a0.a[i] * b1.a[i] + FFT::I * a1.a[i] * b1.a[i];
        }
        u.dft(1);
        v.dft(1);
        a.resize(n);
        for (i = 0; i < n; i++)
            a[i] =
                ((((ll)dtol(u.a[i].x) << 15) % p + dtol(u.a[i].y) + dtol(v.a[i].x) << 15) + dtol(v.a[i].y)) %
                p;
    }
#endif
#else
    Q &operator|=(Q f) {
        ui n = cal(a.size() + f.a.size() - 1);
        a.resize(n);
        f.a.resize(n);
        dft();
        f.dft();
        for (ui i = 0; i < n; i++) a[i] = (ll)a[i] * f.a[i] % p;
        dft(1);
        return *this;
    }
    Q operator|(Q f) const {
        f |= *this;
        return f;
    }
    Q &operator*=(Q f) {
        assert(a.size() == f.a.size());
        ui n = a.size() << 1;
        a.resize(n);
        f.a.resize(n);
        dft();
        f.dft();
        for (ui i = 0; i < n; i++) a[i] = (ll)a[i] * f.a[i] % p;
        dft(1);
        a.resize(n >> 1);
        return *this;
    }
    Q &operator&=(const Q &f) {
        *this |= f;
        int n = a.size(), i;
        for (i = n - 1; i >= 2; i--)
            if (a[i])
                break;
        a.resize(cal(i + 1));
        return *this;
    }
    Q operator&(Q f) const {
        f &= *this;
        return f;
    }
    Q &operator^=(Q f) {
        assert(a.size() == f.a.size());
        ui n = a.size();
        reverse(all(f.a));
        *this |= f;
        copy(a.data() + n - 1, a.data() + n * 2 - 1, a.data());
        a.resize(n);
        return *this;
    }
    Q operator^(const Q &f) const {
        Q g = *this;
        g ^= f;
        return g;
    }
#endif
#ifdef MTT
    Q operator~() {
        Q q = (*this), r(2);
        ui n = a.size() << 1, i, j, k;
        a.resize(n);
        r.a[0] = ksm(a[0], p - 2);
        for (j = 2; j <= n; j <<= 1) {
            k = j >> 1;
            r.a.resize(j);
            q.a.resize(j);
            copy_n(pt(), k, q.pt());
            r = -(q * r - 2) * r;
            r.a.resize(k);
        }
        n >>= 1;
        a.resize(n);
        return r;
    }
#else
    Q operator~() {
        Q q = (*this), r(2), g(2);
        ui n = a.size(), i, j, k;
        r.a[0] = ksm(a[0], p - 2);
        for (j = 2; j <= n; j <<= 1) {
            k = j >> 1;
            r.a.resize(j);
            g = r;
            q.a.resize(j);
            copy_n(pt(), j, q.pt());
            r.dft();
            q.dft();
            for (i = 0; i < j; i++) q.a[i] = (ll)q.a[i] * r.a[i] % p;
            q.dft(1);
            fill_n(q.pt(), k, 0);
            q.dft();
            for (i = 0; i < j; i++) r.a[i] = (ll)q.a[i] * r.a[i] % p;
            r.dft(1);
            copy_n(g.pt(), k, r.pt());
            for (i = k; i < j; i++)
                if (r.a[i])
                    r.a[i] = p - r.a[i];
        }
        return r;
    }
#endif
    Q operator/(Q f) const { return (*this) * ~f; }
    void operator/=(Q f) {
        f = ~f;
        (*this) *= f;
    }
};
Q read(int n) {
    Q r(n);
    int P = p;
    int x;
    for (int i = 0; i < n; i++) cin >> x, r.a[i] = (x % P + P) % P;
    return r;
}
void write(Q &r, int n = -1) {
    if (n == 0)
        return;
    if (n == -1)
        n = r.a.size();
    for (int i = 0; i < n - 1; i++) cout << r.a[i] << " ";
    cout << r.a[n - 1] << endl;
}
#ifndef MTT
Q sqr(Q b) {
    ui n = b.a.size() << 1, i;
    b.a.resize(n);
    b.dft();
    for (i = 0; i < n; i++) b.a[i] = (ll)b.a[i] * b.a[i] % p;
    b.dft(1);
    b.a.resize(n >> 1);
    return b;
}
vector<Q> cd;
void cdq(Q &f, Q &g, ui l, ui r) {
    ui i, m = l + r >> 1, n = r - l, nn = n >> 1;
    if (l == 0 && r == f.a.size()) {
        getinv(n - 1);
        g.a.resize(n);
        for (i = 0; i < n; i++) g.a[i] = 0;
        cd.clear();
        cd.reserve(__builtin_ctz(n));
        Q a(2);
        for (i = 2; i <= n; i <<= 1) {
            a.a.resize(i);
            for (ui j = 0; j < i; j++) a.a[j] = f.a[j];
            a.dft();
            cd.push_back(a);
        }
    }
    if (l + 1 == r) {
        if (l == 0)
            g.a[l] = 1;
        else
            g.a[l] = (ll)g.a[l] * inv[l] % p;
        return;
    }
    cdq(f, g, l, m);
    Q a = cd[__builtin_ctz(n) - 1], b(n);
    for (i = 0; i < nn; i++) b.a[i] = g.a[l + i];
    b.dft();
    for (i = 0; i < n; i++) a.a[i] = (ll)a.a[i] * b.a[i] % p;
    a.dft(1);
    for (i = m; i < r; i++)
        if ((g.a[i] += a.a[i - l]) >= p)
            g.a[i] -= p;
    cdq(f, g, m, r);
}
Q exp_cdq(Q f) {
    Q g(2);
    ui n = f.a.size();
    for (ui i = 1; i < n; i++) f.a[i] = (ll)f.a[i] * i % p;
    cdq(f, g, 0, n);
    return g;
}
Q sqrt(Q b) {
    Q q(2), f(2), r(2);
    ui n = b.a.size();
    int i, j = n, l;
    for (i = 0; i < n; i++)
        if (b.a[i]) {
            j = i;
            break;
        }
    if (j == n)
        return b;
    if (j & 1) {
        puts("-1");
        exit(0);
    }
    l = j >> 1;
    for (i = 0; i < n - j; i++) b.a[i] = b.a[i + j];
    for (i = n - j; i < n; i++) b.a[i] = 0;
    r.a[0] = i = mosqrt(b.a[0]);
    assert(i != -1);
    for (j = 2; j <= n; j <<= 1) {
        r.a.resize(j);
        q = ~r;
        f.a.resize(j << 1);
        for (i = 0; i < j; i++) f.a[i] = b.a[i];
        q.a.resize(j << 1);
        r.a.resize(j << 1);
        q.dft();
        r.dft();
        f.dft();
        for (i = 0; i < j << 1; i++)
            if ((r.a[i] = (ll)q.a[i] * ((ll)r.a[i] * r.a[i] % p + f.a[i]) % p) & 1)
                r.a[i] = r.a[i] + p >> 1;
            else
                r.a[i] >>= 1;
        r.dft(1);
        for (i = j; i < j << 1; i++) r.a[i] = 0;
    }
    r.a.resize(n);
    for (i = n - 1; i >= l; i--) r.a[i] = r.a[i - l];
    for (i = 0; i < l; i++) r.a[i] = 0;
    return r;
}
#endif
Q ln(Q b) { return (b.dao() / b).ji(); }
#ifdef MTT
Q exp(Q f) {
    Q q(2), r(2);
    ui n = f.a.size() << 1, i, j, k;
    r.a[0] = 1;
    for (j = 2; j <= n; j <<= 1) {
        k = j >> 1;
        r.a.resize(j);
        q.a.resize(j);
        for (i = 0; i < k; i++) q.a[i] = f.a[i];
        r = r * (q - ln(r) + 1);
        r.a.resize(k);
    }
    return r;
}
#else
Q exp(Q b) {
    Q q(2), r(2);
    ui n = b.a.size(), i, j;
    r.a[0] = 1;
    for (j = 2; j <= n; j <<= 1) {
        r.a.resize(j);
        q = ln(r);
        for (i = 0; i < j; i++)
            if ((q.a[i] = b.a[i] + p - q.a[i]) >= p)
                q.a[i] -= p;
        (++q.a[0]) %= p;
        r.a.resize(j << 1);
        q.a.resize(j << 1);
        r.dft();
        q.dft();
        for (i = 0; i < j << 1; i++) r.a[i] = (ll)r.a[i] * q.a[i] % p;
        r.dft(1);
        r.a.resize(j);
    }
    return r;
}
void mul(Q &a, Q &b) {
    ui n = a.a.size();
    a.dft();
    b.dft();
    for (ui i = 0; i < n; i++) a.a[i] = (ll)a.a[i] * b.a[i] % p;
    a.dft(1);
}
Q exp_new(Q b) {
    Q h(2), f(2), r(2), u(2), v(2);
    ui n = b.a.size(), i, j, k;
    r.a[0] = 1;
    h.a[0] = 1;
    for (j = 2; j <= n; j <<= 1) {
        f.a.resize(j);
        for (i = 0; i < j; i++) f.a[i] = b.a[i];
        f = f.dao();
        k = j >> 1;
        for (i = 0; i < k - 1; i++) {
            if ((f.a[i + k] += f.a[i]) >= p)
                f.a[i + k] -= p;
            f.a[i] = 0;
        }
        for (i = k - 1; i < j; i++)
            if (f.a[i])
                f.a[i] = p - f.a[i];
        u.a.resize(k);
        v.a.resize(k);
        copy_n(r.pt(), k, u.pt());
        copy_n(h.pt(), k, v.pt());
        u = u.dao();
        mul(u, v);
        for (i = 0; i < k - 1; i++)
            if ((f.a[i + k] += u.a[i]) >= p)
                f.a[i + k] -= p;
        if ((f.a[k - 1] += u.a[k - 1]) >= p)
            f.a[k - 1] -= p;
        copy_n(r.pt(), k, u.pt());
        u.dft();
        for (i = 0; i < k; i++) u.a[i] = (ll)u.a[i] * v.a[i] % p;
        u.dft(1);
        (u.a[0] += p - 1) %= p;
        u.a.resize(j);
        v.a.resize(j);
        copy_n(b.pt(), k, v.pt());
        v = v.dao();
        mul(u, v);
        for (i = 0; i < k; i++)
            if (f.a[i + k] < u.a[i])
                f.a[i + k] += p - u.a[i];
            else
                f.a[i + k] -= u.a[i];
        f = f.ji();
        copy_n(r.pt(), k, u.pt());
        fill_n(u.pt() + k, k, 0);
        mul(u, f);
        r.a.resize(j);
        for (i = k; i < j; i++)
            if (u.a[i])
                r.a[i] = p - u.a[i];
            else
                r.a[i] = 0;
        if (j != n)
            h = ~r;
    }
    return r;
}
Q sqrt_new(Q b) {
    Q q(2), r(2), h(2);
    ui n = b.a.size();
    int i, j = n, k, l;
    for (i = 0; i < n; i++)
        if (b.a[i]) {
            j = i;
            break;
        }
    if (j == n)
        return b;
    if (j & 1) {
        puts("-1");
        exit(0);
    }
    l = j >> 1;
    for (i = 0; i < n - j; i++) b.a[i] = b.a[i + j];
    for (i = n - j; i < n; i++) b.a[i] = 0;
    r.a[0] = mosqrt(b.a[0]);
    h.a[0] = ksm(r.a[0], p - 2);
    r.a.resize(1);
    ui i2 = ksm(2, p - 2);
    for (j = 2; j <= n; j <<= 1) {
        k = j >> 1;
        q = r;
        q.dft();
        for (i = 0; i < k; i++) q.a[i] = (ll)q.a[i] * q.a[i] % p;
        q.dft(1);
        q.a.resize(j);
        for (i = k; i < j; i++) q.a[i] = (ll)(q.a[i - k] + p * 2u - b.a[i] - b.a[i - k]) * i2 % p;
        for (i = 0; i < k; i++) q.a[i] = 0;
        h.a.resize(j);
        mul(q, h);
        r.a.resize(j);
        for (i = k; i < j; i++)
            if (q.a[i])
                r.a[i] = p - q.a[i];
        if (j != n)
            h = ~r;
    }
    r.a.resize(n);
    for (i = n - 1; i >= l; i--) r.a[i] = r.a[i - l];
    for (i = 0; i < l; i++) r.a[i] = 0;
    return r;
}
Q pow(Q b, ui m) {
    ui n = b.a.size();
    int i, j = n, k;
    for (i = 0; i < n; i++)
        if (b.a[i]) {
            j = i;
            break;
        }
    if (j == n)
        return b;
    if ((ll)j * m >= n) {
        fill_n(b.pt(), n, 0);
        return b;
    }
    for (i = 0; i < n - j; i++) b.a[i] = b.a[i + j];
    for (i = n - j; i < n; i++) b.a[i] = 0;
    k = b.a[0];
    assert(k);
    b = exp_new(ln(b * ksm(k, p - 2)) * m) * ksm(k, m);
    j *= m;
    for (i = n - 1; i >= j; i--) b.a[i] = b.a[i - j];
    for (i = 0; i < j; i++) b.a[i] = 0;
    return b;
}
Q pow(Q b, string s) {
    ui n = b.a.size();
    int i, j = n, k;
    for (i = 0; i < n; i++)
        if (b.a[i]) {
            j = i;
            break;
        }
    if (j == n)
        return b;
    if (j) {
        if (s.size() > 8 || j * stoll(s) >= n) {
            fill_n(b.pt(), n, 0);
            return b;
        }
    }
    ui m0 = 0, m1 = 0;
    for (auto c : s) m0 = (m0 * 10ll + c - '0') % p, m1 = (m1 * 10ll + c - '0') % (p - 1);
    for (i = 0; i < n - j; i++) b.a[i] = b.a[i + j];
    for (i = n - j; i < n; i++) b.a[i] = 0;
    k = b.a[0];
    assert(k);
    b = exp_new(ln(b * ksm(k, p - 2)) * m0) * ksm(k, m1);
    j *= m0;
    for (i = n - 1; i >= j; i--) b.a[i] = b.a[i - j];
    for (i = 0; i < j; i++) b.a[i] = 0;
    return b;
}
Q pow2(Q b, ui m) {
    Q r(b.a.size());
    r.a[0] = 1;
    while (m) {
        if (m & 1)
            r = r * b;
        if (m >>= 1)
            b = b * b;
    }
    return r;
}
pair<Q, Q> div(Q a, Q b) {
    int n = 0, m = 0, l, i, nn = a.a.size();
    for (i = a.a.size() - 1; i >= 0; i--)
        if (a.a[i]) {
            n = i + 1;
            break;
        }
    for (i = b.a.size() - 1; i >= 0; i--)
        if (b.a[i]) {
            m = i + 1;
            break;
        }
    assert(m);
    if (n < m)
        return make_pair(Q(2), a);
    l = cal(n + m - 1);
    Q c(n), d(m);
    reverse_copy(a.a.data(), a.a.data() + n, c.a.data());
    reverse_copy(b.a.data(), b.a.data() + m, d.a.data());
    c.a.resize(cal(n - m + 1));
    d.a.resize(c.a.size());
    d = ~d;
    for (i = n - m + 1; i < c.a.size(); i++) c.a[i] = d.a[i] = 0;
    c *= d;
    for (i = n - m + 1; i < c.a.size(); i++) c.a[i] = 0;
    reverse(c.a.data(), c.a.data() + n - m + 1);
    n = a.a.size();
    b.a.resize(n);
    c.a.resize(n);
    d = a - c * b;
    for (i = m; i < d.a.size(); i++) assert(d.a[i] == 0);
    c.a.resize(cal(n - m + 1));
    d.a.resize(cal(m));
    return make_pair(c, d);
}
Q sin(Q &f) { return (exp(f * I) - exp(f * (p - I))) * ksm(2 * I % p, p - 2); }
Q cos(Q &f) { return (exp(f * I) + exp(f * (p - I))) * ksm(2, p - 2); }
Q tan(Q &f) { return sin(f) / cos(f); }
Q asin(Q &f) { return (f.dao() / sqrt((f * f - 1) * (p - 1))).ji(); }
Q acos(Q &f) { return ((f.dao() / sqrt((f * f - 1) * (p - 1))) * (p - 1)).ji(); }
Q atan(Q &f) { return (f.dao() / (f * f + 1)).ji(); }
Q cdq_inv(Q &f) { return (~(f - 1)) * (p - 1); }
Q operator%(Q f, Q g) { return div(f, g).second; }
void operator%=(Q &f, const Q &g) { f = f % g; }
vector<Q> pro;
ui *X;
vector<ui> Y;
const int get_fx_lim2 = 30;
vector<Q> sum;
const ui B = 1e5;
ui a[B + 2], b[B + 2];
ui mic(ui x) { return (ll)a[x % B] * b[x / B] % p; }
#endif
}  // namespace NTT
#define int long long

using NTT::p;
using NTT::read;
using NTT::ui;
#define poly NTT::Q

const int Mod = 998244353;
#define Max 500005

int qpw(int a, int b) {
    int res = 1;
    while (b) {
        if (b & 1)
            res = res * a % Mod;
        //		cout<<a<<' '<<b<<' '<<res<<"\n";
        a = a * a % Mod;
        b >>= 1;
    }
    return res;
}
int fac[Max], ifac[Max];
signed main() {
    //	freopen("10.in","r",stdin);
    //	freopen("10.out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(0);
    int n, k;
    cin >> n >> k;
    poly f(n + 1);
    fac[0] = ifac[0] = 1;
    for (int i = 1; i <= n; i++) {
        fac[i] = fac[i - 1] * i % Mod;
    }
    ifac[n] = qpw(fac[n], Mod - 2);
    for (int i = n - 1; i >= 1; i--) ifac[i] = ifac[i + 1] * (i + 1) % Mod;
    for (int i = 0; i <= n; i++) {
        f.a[i] = ifac[i] * qpw(2, i * (i - 1) / 2 % (Mod - 1)) % Mod;
    }
    auto g = (~f);
    for (int i = 0; i <= n; i++) g.a[i] = (Mod - g.a[i]) % Mod;
    g.a[0] = (g.a[0] + 1) % Mod;
    int mx = 1;
    for (int i = 1; i <= k; i++) {
        int w;
        cin >> w;
        if (w == 2) {
            puts("0");
            return 0;
        }
        mx = max(mx, w);
    }
    for (int i = mx; i <= n; i++) g.a[i] = 0;

    for (int i = 0; i <= n; i++) g.a[i] = (Mod - g.a[i]) % Mod;
    g.a[0] += 1;
    auto res1 = ~g;
    cout << (f.a[n] * fac[n] % Mod - res1.a[n] * fac[n] % Mod + Mod) % Mod << "\n";
}
子任务 #1
Accepted
得分:100
测试点 #1
Accepted
得分:100
用时:139 ms
内存:6488 KiB

输入文件(1.in

100000 500
31599 6915 91270 1661 29829 55647 23911 18968 18394 72717 62694 72888 68356 45622 52749 
<2852 bytes omitted>

答案文件(1.out

415282073

用户输出

415282073

系统信息

Exited with return code 0
测试点 #2
Accepted
得分:100
用时:137 ms
内存:6488 KiB

输入文件(2.in

100000 5000
29529 44280 90141 35177 83295 17947 47455 86819 74799 2831 38016 37929 32078 44918 9612
<29380 bytes omitted>

答案文件(2.out

388342451

用户输出

388342451

系统信息

Exited with return code 0
测试点 #3
Accepted
得分:100
用时:139 ms
内存:6484 KiB

输入文件(3.in

100000 50000
33701 67714 2164 72781 30104 88239 14380 54251 1838 85079 79349 38676 50112 58278 8238
<294292 bytes omitted>

答案文件(3.out

468044740

用户输出

468044740

系统信息

Exited with return code 0
测试点 #4
Accepted
得分:100
用时:144 ms
内存:6416 KiB

输入文件(4.in

100000 98000
66276 9593 83741 31550 23402 57841 26379 16990 13649 32430 24627 79388 13060 9862 1235
<577030 bytes omitted>

答案文件(4.out

854278657

用户输出

854278657

系统信息

Exited with return code 0
测试点 #5
Accepted
得分:100
用时:89 ms
内存:5756 KiB

输入文件(5.in

100000 98000
61690 76514 14331 51908 13421 21209 75656 28275 72507 28774 5129 51191 10746 30776 689
<577040 bytes omitted>

答案文件(5.out

0

用户输出

0

系统信息

Exited with return code 0
测试点 #6
Accepted
得分:100
用时:141 ms
内存:6424 KiB

输入文件(6.in

100000 98123
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 
<577555 bytes omitted>

答案文件(6.out

657420631

用户输出

657420631

系统信息

Exited with return code 0
测试点 #7
Accepted
得分:100
用时:80 ms
内存:5852 KiB

输入文件(7.in

100000 98123
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 3
<577551 bytes omitted>

答案文件(7.out

0

用户输出

0

系统信息

Exited with return code 0
测试点 #8
Accepted
得分:100
用时:135 ms
内存:6472 KiB

输入文件(8.in

99999 5
67820 82839 68514 54839 53794

答案文件(8.out

164481186

用户输出

164481186

系统信息

Exited with return code 0
测试点 #9
Accepted
得分:100
用时:136 ms
内存:6480 KiB

输入文件(9.in

99999 5
3 4 5 6 7

答案文件(9.out

733878736

用户输出

733878736

系统信息

Exited with return code 0
测试点 #10
Accepted
得分:100
用时:135 ms
内存:6480 KiB

输入文件(10.in

99999 50
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 3
<54 bytes omitted>

答案文件(10.out

832923316

用户输出

832923316

系统信息

Exited with return code 0