Cells(2021牛客暑期多校训练营9 C,LGV引理 + 范德蒙德行列式 + NTT)

Kakao-Valhalla:A2V第一个项目_kakao-arena 卡卡奥竞技场->瓦尔哈拉 Kakao-Arena를(Arena)상의이상의(Valhalla)로。 (참여가능한설계) 는리는Kakao-arena(1。대한Demiguises팀의아이디어를다)。 介绍 는리는竞赛test竞赛이자贡献者로서이대회를지는로전장으다만들고자다。 原样 数据处理(数据处理)和数据下载。 달달달달달달달달있발하있있있있있있있있있있있있있있있있있있있。 스스로생각하거나생각하거나생각하거나생각하거나생각하거나를활동대회대회대회대회대회목대회대회대회목목목목목목목목목목목목목목목목목。 成为 우 리 는 그 러 한 제 약 을 최 소 화 하 고 , 대 회 立即下载

一、题目链接

Cells

二、题目大意

在一个二维平面内,有 n n n 个起点 ( 0 , a i ) (0, a_i) (0,ai​) 要走到对应的终点 ( i , 0 ) (i, 0) (i,0),每次可以向下走或向左走,问不相交路径组的方案数.

1 ≤ n ≤ 5 × 1 0 5 , 0 ≤ a i ≤ 1 0 6 , a i < a i + 1 1 \leq n \leq 5 \times 10^5, 0 \leq a_i \leq 10^6, a_i < a_{i+1} 1≤n≤5×105,0≤ai​≤106,ai​<ai+1​.

三、分析

易知从 ( 0 , a i ) (0, a_i) (0,ai​) 走到 ( j , 0 ) (j,0) (j,0) 的方案数为 ( a i + j j ) \binom{a_i + j}{j} (jai​+j​).
M = [ ( a 1 + 1 1 ) ( a 1 + 2 2 ) ⋯ ( a 1 + n n ) ( a 2 + 1 1 ) ( a 2 + 2 2 ) ⋯ ( a 2 + n n ) ⋮ ⋮ ⋯ ⋮ ( a n + 1 1 ) ( a n + 2 2 ) ⋯ ( a n + n n ) ] M = \left [ \begin{matrix} \binom{a_1 + 1}{1} & \binom{a_1 + 2}{2} & \cdots & \binom{a_1 + n}{n} \\ \binom{a_2 + 1}{1} & \binom{a_2 + 2}{2} & \cdots & \binom{a_2 + n}{n} \\ \vdots & \vdots & \cdots & \vdots \\ \binom{a_n + 1}{1} & \binom{a_n + 2}{2} & \cdots & \binom{a_n + n}{n} \end{matrix} \right] M=⎣⎢⎢⎢⎡​(1a1​+1​)(1a2​+1​)⋮(1an​+1​)​(2a1​+2​)(2a2​+2​)⋮(2an​+2​)​⋯⋯⋯⋯​(na1​+n​)(na2​+n​)⋮(nan​+n​)​⎦⎥⎥⎥⎤​
则由 LGV 引理可知 ∣ M ∣ |M| ∣M∣ 即为答案.

由于 m a x ( n ) = 5 × 1 0 5 max(n) = 5 \times 10^5 max(n)=5×105,直接高斯消元是无法承受的,考虑简便计算 ∣ M ∣ |M| ∣M∣ 的方法.
∣ M ∣ = ∣ ( a 1 + 1 1 ) ( a 1 + 2 2 ) ⋯ ( a 1 + n n ) ( a 2 + 1 1 ) ( a 2 + 2 2 ) ⋯ ( a 2 + n n ) ⋮ ⋮ ⋯ ⋮ ( a n + 1 1 ) ( a n + 2 2 ) ⋯ ( a n + n n ) ∣ = ∣ ( a 1 + 1 ) ! 1 ! a 1 ! ( a 1 + 2 ) ! 2 ! a 1 ! ⋯ ( a 1 + n ) ! n ! a 1 ! ( a 2 + 1 ) ! 1 ! a 2 ! ( a 2 + 2 ) ! 2 ! a 2 ! ⋯ ( a 2 + n ) ! n ! a 2 ! ⋮ ⋮ ⋯ ⋮ ( a n + 1 ) ! 1 ! a n ! ( a n + 2 ) ! 2 ! a n ! ⋯ ( a n + n ) ! n ! a n ! ∣ = ∏ i = 1 n 1 i ! ∣ ( a 1 + 1 ) ! a 1 ! ( a 1 + 2 ) ! a 1 ! ⋯ ( a 1 + n ) ! a 1 ! ( a 2 + 1 ) ! a 2 ! ( a 2 + 2 ) ! a 2 ! ⋯ ( a 2 + n ) ! a 2 ! ⋮ ⋮ ⋯ ⋮ ( a n + 1 ) ! a n ! ( a n + 2 ) ! a n ! ⋯ ( a n + n ) ! a n ! ∣ = ∏ i = 1 n 1 i ! ∣ ( a 1 + 1 ) ( a 1 + 1 ) ( a 1 + 2 ) ⋯ ∏ i = 1 n ( a 1 + i ) ( a 2 + 1 ) ( a 2 + 1 ) ( a 2 + 2 ) ⋯ ∏ i = 1 n ( a 2 + i ) ⋮ ⋮ ⋯ ⋮ ( a n + 1 ) ( a n + 1 ) ( a n + 2 ) ⋯ ∏ i = 1 n ( a n + i ) ∣ = ∏ i = 1 n 1 i ! ∣ ( a 1 + 1 ) ( a 2 + 1 ) ⋯ ( a n + 1 ) ( a 1 + 1 ) ( a 1 + 2 ) ( a 2 + 1 ) ( a 2 + 2 ) ⋯ ( a n + 1 ) ( a n + 2 ) ⋮ ⋮ ⋯ ⋮ ∏ i = 1 n ( a 1 + i ) ∏ i = 1 n ( a 2 + i ) ⋯ ∏ i = 1 n ( a n + i ) ∣ = ∏ i = 1 n 1 i ! ∣ ( a 1 + 1 ) ( a 2 + 1 ) ⋯ ( a n + 1 ) ( a 1 + 1 ) 2 ( a 2 + 1 ) 2 ⋯ ( a n + 1 ) 2 ⋮ ⋮ ⋯ ⋮ ( a 1 + 1 ) n ( a 2 + 1 ) n ⋯ ( a n + 1 ) n ∣ = ∏ i = 1 n a i + 1 i ! ∣ 1 1 ⋯ 1 a 1 + 1 a 2 + 1 ⋯ a n + 1 ⋮ ⋮ ⋯ ⋮ ( a 1 + 1 ) n − 1 ( a 2 + 1 ) n − 1 ⋯ ( a n + 1 ) n − 1 ∣ = ∏ i = 1 n a i + 1 i ! ∏ j = 1 i − 1 ( a i − a j ) \begin{aligned} |M| &= \left | \begin{matrix} \binom{a_1 + 1}{1} & \binom{a_1 + 2}{2} & \cdots & \binom{a_1 + n}{n} \\ \binom{a_2 + 1}{1} & \binom{a_2 + 2}{2} & \cdots & \binom{a_2 + n}{n} \\ \vdots & \vdots & \cdots & \vdots \\ \binom{a_n + 1}{1} & \binom{a_n + 2}{2} & \cdots & \binom{a_n + n}{n} \end{matrix} \right| \\ &= \left | \begin{matrix} \frac{(a_1 + 1)!}{1!a_1!} & \frac{(a_1 + 2)!}{2!a_1!} & \cdots & \frac{(a_1 + n)!}{n!a_1!} \\ \frac{(a_2 + 1)!}{1!a_2!} & \frac{(a_2 + 2)!}{2!a_2!} & \cdots & \frac{(a_2 + n)!}{n!a_2!} \\ \vdots & \vdots & \cdots & \vdots \\ \frac{(a_n + 1)!}{1!a_n!} & \frac{(a_n + 2)!}{2!a_n!} & \cdots & \frac{(a_n + n)!}{n!a_n!} \\ \end{matrix} \right| \\ &= \prod_{i=1}^n{\frac{1}{i!}}\left | \begin{matrix} \frac{(a_1 + 1)!}{a_1!} & \frac{(a_1 + 2)!}{a_1!} & \cdots & \frac{(a_1 + n)!}{a_1!} \\ \frac{(a_2 + 1)!}{a_2!} & \frac{(a_2 + 2)!}{a_2!} & \cdots & \frac{(a_2 + n)!}{a_2!} \\ \vdots & \vdots & \cdots & \vdots \\ \frac{(a_n + 1)!}{a_n!} & \frac{(a_n + 2)!}{a_n!} & \cdots & \frac{(a_n + n)!}{a_n!} \\ \end{matrix} \right| \\ &= \prod_{i=1}^n{\frac{1}{i!}}\left | \begin{matrix} (a_1 + 1) & (a_1 + 1)(a_1 + 2) & \cdots & \prod_{i=1}^n{(a_1 + i)} \\ (a_2 + 1) & (a_2 + 1)(a_2 + 2) & \cdots & \prod_{i=1}^n{(a_2 + i)} \\ \vdots & \vdots & \cdots & \vdots \\ (a_n + 1) & (a_n + 1)(a_n + 2) & \cdots & \prod_{i=1}^n{(a_n + i)} \\ \end{matrix} \right| \\ &= \prod_{i=1}^n{\frac{1}{i!}}\left | \begin{matrix} (a_1 + 1) & (a_2 + 1) & \cdots & (a_n + 1) \\ (a_1 + 1)(a_1 + 2) & (a_2 + 1)(a_2 + 2) & \cdots & (a_n + 1)(a_n + 2) \\ \vdots & \vdots & \cdots & \vdots \\ \prod_{i=1}^n{(a_1 + i)} & \prod_{i=1}^n{(a_2 + i)} & \cdots & \prod_{i=1}^n{(a_n + i)} \\ \end{matrix} \right| \\ &= \prod_{i=1}^n{\frac{1}{i!}}\left | \begin{matrix} (a_1 + 1) & (a_2 + 1) & \cdots & (a_n + 1) \\ (a_1 + 1)^2 & (a_2 + 1)^2 & \cdots & (a_n + 1)^2 \\ \vdots & \vdots & \cdots & \vdots \\ (a_1 + 1)^n & (a_2 + 1)^n & \cdots & (a_n + 1)^n \\ \end{matrix} \right| \\ &= \prod_{i=1}^n{\frac{a_i + 1}{i!}}\left | \begin{matrix} 1 & 1 & \cdots & 1 \\ a_1 + 1 & a_2 + 1 & \cdots & a_n + 1 \\ \vdots & \vdots & \cdots & \vdots \\ (a_1 + 1)^{n-1} & (a_2 + 1)^{n-1} & \cdots & (a_n + 1)^{n-1} \\ \end{matrix} \right| \\ &= \prod_{i=1}^n{\frac{a_i + 1}{i!} \prod_{j=1}^{i-1}{(a_i - a_j)}} \end{aligned} ∣M∣​=∣∣∣∣∣∣∣∣∣​(1a1​+1​)(1a2​+1​)⋮(1an​+1​)​(2a1​+2​)(2a2​+2​)⋮(2an​+2​)​⋯⋯⋯⋯​(na1​+n​)(na2​+n​)⋮(nan​+n​)​∣∣∣∣∣∣∣∣∣​=∣∣∣∣∣∣∣∣∣∣​1!a1​!(a1​+1)!​1!a2​!(a2​+1)!​⋮1!an​!(an​+1)!​​2!a1​!(a1​+2)!​2!a2​!(a2​+2)!​⋮2!an​!(an​+2)!​​⋯⋯⋯⋯​n!a1​!(a1​+n)!​n!a2​!(a2​+n)!​⋮n!an​!(an​+n)!​​∣∣∣∣∣∣∣∣∣∣​=i=1∏n​i!1​∣∣∣∣∣∣∣∣∣∣​a1​!(a1​+1)!​a2​!(a2​+1)!​⋮an​!(an​+1)!​​a1​!(a1​+2)!​a2​!(a2​+2)!​⋮an​!(an​+2)!​​⋯⋯⋯⋯​a1​!(a1​+n)!​a2​!(a2​+n)!​⋮an​!(an​+n)!​​∣∣∣∣∣∣∣∣∣∣​=i=1∏n​i!1​∣∣∣∣∣∣∣∣∣​(a1​+1)(a2​+1)⋮(an​+1)​(a1​+1)(a1​+2)(a2​+1)(a2​+2)⋮(an​+1)(an​+2)​⋯⋯⋯⋯​∏i=1n​(a1​+i)∏i=1n​(a2​+i)⋮∏i=1n​(an​+i)​∣∣∣∣∣∣∣∣∣​=i=1∏n​i!1​∣∣∣∣∣∣∣∣∣​(a1​+1)(a1​+1)(a1​+2)⋮∏i=1n​(a1​+i)​(a2​+1)(a2​+1)(a2​+2)⋮∏i=1n​(a2​+i)​⋯⋯⋯⋯​(an​+1)(an​+1)(an​+2)⋮∏i=1n​(an​+i)​∣∣∣∣∣∣∣∣∣​=i=1∏n​i!1​∣∣∣∣∣∣∣∣∣​(a1​+1)(a1​+1)2⋮(a1​+1)n​(a2​+1)(a2​+1)2⋮(a2​+1)n​⋯⋯⋯⋯​(an​+1)(an​+1)2⋮(an​+1)n​∣∣∣∣∣∣∣∣∣​=i=1∏n​i!ai​+1​∣∣∣∣∣∣∣∣∣​1a1​+1⋮(a1​+1)n−1​1a2​+1⋮(a2​+1)n−1​⋯⋯⋯⋯​1an​+1⋮(an​+1)n−1​∣∣∣∣∣∣∣∣∣​=i=1∏n​i!ai​+1​j=1∏i−1​(ai​−aj​)​
至此计算 ∣ M ∣ |M| ∣M∣ 是 O ( n 2 ) O(n^2) O(n2) 的,依然不可接受,考虑如何快速计算 ∏ j = 1 i − 1 a i − a j \begin{aligned} \prod_{j=1}^{i-1}{a_i - a_j} \end{aligned} j=1∏i−1​ai​−aj​​.

记 f ( x ) = ∑ i = 1 n x a i \begin{aligned} f(x) = \sum_{i=1}^{n}{x^{a_i}}\end{aligned} f(x)=i=1∑n​xai​​, g ( x ) = ∑ i = 1 n x − a i \begin{aligned}g(x) = \sum_{i=1}^{n}{x^{-a_i}} \end{aligned} g(x)=i=1∑n​x−ai​​.

用 NTT 处理出 h = f ∗ g = ∑ c i x i \begin{aligned} h = f*g = \sum{c_ix^i} \end{aligned} h=f∗g=∑ci​xi​.

按 ( a i − a j ) (a_i - a_j) (ai​−aj​) 计算贡献,则 ∏ i = 1 n ∏ j = 1 i − 1 ( a i − a j ) = ∏ i > 0 i c i \begin{aligned} \prod_{i=1}^n{\prod_{j=1}^{i-1}(a_i - a_j)} = \prod_{i > 0}{i^{c_i}} \end{aligned} i=1∏n​j=1∏i−1​(ai​−aj​)=i>0∏​ici​​.

因此答案为 ∏ i = 1 n a i + 1 i ! × ∏ i > 0 i c i \begin{aligned} \prod_{i=1}^{n}{\frac{a_i + 1}{i!}} \times \prod_{i>0}{i^{c_i}} \end{aligned} i=1∏n​i!ai​+1​×i>0∏​ici​​.

四、代码实现

#include <bits/stdc++.h>
using namespace std;

template <typename T>
inline void read(T& x)
{
    x = 0; int f = 1; char ch = getchar();
    while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
    while(isdigit(ch))  {x = x * 10 + ch - '0', ch = getchar();}
    x *= f;
}

template <typename T>
void print(T x)
{
    if(x < 0) putchar('-'), x = -x;
    if(x > 9) print(x / 10);
    putchar(x % 10 + '0');
}

template <typename T>
void print(T x, char ch)
{
    print(x), putchar(ch);
}

typedef double db;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;

template <ui M_> struct ModInt {
    static constexpr ui M = M_;
    ui x;
    constexpr ModInt(): x(0U){}
    constexpr ModInt(ui x_): x(x_ % M){}
    constexpr ModInt(ull x_): x(x_ % M){}
    constexpr ModInt(int x_): x(((x_ %= static_cast<int>(M)) < 0) ? (x_ + static_cast<int>(M)) : x_){}
    constexpr ModInt(ll x_): x(((x_ %= static_cast<ll>(M)) < 0) ? (x_ + static_cast<ll>(M)) : x_){}
    ModInt &operator+=(const ModInt &a) {x = ((x += a.x) >= M) ? (x - M) : x; return *this;}
    ModInt &operator-=(const ModInt &a) {x = ((x -= a.x) >= M) ? (x + M) : x; return *this;}
    ModInt &operator*=(const ModInt &a) {x = (static_cast<ull>(x) * a.x) % M; return *this;}
    ModInt &operator/=(const ModInt &a) {return (*this *= a.inv());}
    ModInt pow(ll e) const {
        if(e < 0) return inv().pow(-e);
        ModInt a = *this, b = 1U; for(; e; e >>= 1) {if(e & 1) b *= a; a *= a;} return b;
    }
    ModInt inv() const {
        ui a = M, b = x; int y = 0, z = 1;
        while(b) {const ui q = a / b; const ui c = a - q * b; a = b; b = c; const int w = y - static_cast<int>(q) * z; y = z; z = w;}
        return ModInt(y);
    }
    ModInt operator+() const {return *this;}
    ModInt operator-() const {ModInt a; a.x = x ? (M - x) : 0U; return a;}
    ModInt operator+(const ModInt &a) const {return (ModInt(*this) += a);}
    ModInt operator-(const ModInt &a) const {return (ModInt(*this) -= a);}
    ModInt operator*(const ModInt &a) const {return (ModInt(*this) *= a);}
    ModInt operator/(const ModInt &a) const {return (ModInt(*this) /= a);}
    template <class T> friend ModInt operator+(T a, const ModInt &b) {return (ModInt(a) += b);}
    template <class T> friend ModInt operator-(T a, const ModInt &b) {return (ModInt(a) -= b);}
    template <class T> friend ModInt operator*(T a, const ModInt &b) {return (ModInt(a) *= b);}
    template <class T> friend ModInt operator/(T a, const ModInt &b) {return (ModInt(a) /= b);}
    explicit operator bool() const {return x;}
    bool operator==(const ModInt &a) const {return (x == a.x);}
    bool operator!=(const ModInt &a) const {return (x != a.x);}
    friend std::ostream &operator<<(std::ostream &os, const ModInt &a) {return os << a.x;}
};

constexpr unsigned MO = 998244353U;
constexpr unsigned MO2 = 2U * MO;
constexpr int FFT_MAX = 23;
using Mint = ModInt<MO>;
constexpr Mint FFT_ROOTS[FFT_MAX + 1] = {1U, 998244352U, 911660635U, 372528824U, 929031873U, 452798380U, 922799308U, 781712469U, 476477967U, 166035806U, 258648936U, 584193783U, 63912897U, 350007156U, 666702199U, 968855178U, 629671588U, 24514907U, 996173970U, 363395222U, 565042129U, 733596141U, 267099868U, 15311432U};
constexpr Mint INV_FFT_ROOTS[FFT_MAX + 1] = {1U, 998244352U, 86583718U, 509520358U, 337190230U, 87557064U, 609441965U, 135236158U, 304459705U, 685443576U, 381598368U, 335559352U, 129292727U, 358024708U, 814576206U, 708402881U, 283043518U, 3707709U, 121392023U, 704923114U, 950391366U, 428961804U, 382752275U, 469870224U};
constexpr Mint FFT_RATIOS[FFT_MAX] = {911660635U, 509520358U, 369330050U, 332049552U, 983190778U, 123842337U, 238493703U, 975955924U, 603855026U, 856644456U, 131300601U, 842657263U, 730768835U, 942482514U, 806263778U, 151565301U, 510815449U, 503497456U, 743006876U, 741047443U, 56250497U, 867605899U};
constexpr Mint INV_FFT_RATIOS[FFT_MAX] = {86583718U, 372528824U, 373294451U, 645684063U, 112220581U, 692852209U, 155456985U, 797128860U, 90816748U, 860285882U, 927414960U, 354738543U, 109331171U, 293255632U, 535113200U, 308540755U, 121186627U, 608385704U, 438932459U, 359477183U, 824071951U, 103369235U};

void fft(Mint *as, int n) {
    int m = n;
    if(m >>= 1) {
        for(int i = 0; i < m; ++i) {
            const ui x = as[i + m].x;
            as[i + m].x = as[i].x + MO - x;
            as[i].x += x;
        }
    }
    if(m >>= 1) {
        Mint prod = 1U;
        for(int h = 0, i0 = 0; i0 < n; i0 += (m<<1)) {
            for(int i = i0; i < i0 + m; ++i) {
                const ui x = (prod * as[i + m]).x;
                as[i + m].x = as[i].x + MO - x;
                as[i].x += x;
            }
            prod *= FFT_RATIOS[__builtin_ctz(++h)];
        }
    }
    while(m) {
        if(m >>= 1) {
            Mint prod = 1U;
            for(int h = 0, i0 = 0; i0 < n; i0 += (m<<1)) {
                for(int i = i0; i < i0 + m; ++i) {
                    const ui x = (prod * as[i + m]).x;
                    as[i + m].x = as[i].x + MO - x;
                    as[i].x += x;
                }
                prod *= FFT_RATIOS[__builtin_ctz(++h)];
            }
        }
        if(m >>= 1) {
            Mint prod = 1U;
            for(int h = 0, i0 = 0; i0 < n; i0 += (m<<1)) {
                for(int i = i0; i < i0 + m; ++i) {
                    const ui x = (prod * as[i + m]).x;
                    as[i].x = (as[i].x >= MO2) ? (as[i].x - MO2) : as[i].x;
                    as[i + m].x = as[i].x + MO - x;
                    as[i].x += x;
                }
                prod *= FFT_RATIOS[__builtin_ctz(++h)];
            }
        }
    }
    for(int i = 0; i < n; ++i) {
        as[i].x = (as[i].x >= MO2) ? (as[i].x - MO2) : as[i].x;
        as[i].x = (as[i].x >= MO) ? (as[i].x - MO) : as[i].x;
    }
}

void invFft(Mint *as, int n) {
    int m = 1;
    if(m < n>>1) {
        Mint prod = 1U;
        for(int h = 0, i0 = 0; i0 < n; i0 += (m<<1)) {
            for(int i = i0; i < i0 + m; ++i) {
                const ull y = as[i].x + MO - as[i + m].x;
                as[i].x += as[i + m].x;
                as[i + m].x = (prod.x * y) % MO;
            }
            prod *= INV_FFT_RATIOS[__builtin_ctz(++h)];
        }
        m <<= 1;
    }
    for(; m < n>>1; m <<= 1) {
        Mint prod = 1U;
        for(int h = 0, i0 = 0; i0 < n; i0 += (m<<1)) {
            for(int i = i0; i < i0 + (m>>1); ++i) {
                const ull y = as[i].x + MO2 - as[i + m].x;
                as[i].x += as[i + m].x;
                as[i].x = (as[i].x >= MO2) ? (as[i].x - MO2) : as[i].x;
                as[i + m].x = (prod.x * y) % MO;
            }
            for(int i = i0 + (m>>1); i < i0 + m; ++i) {
                const ull y = as[i].x + MO - as[i + m].x;
                as[i].x += as[i + m].x;
                as[i + m].x = (prod.x * y) % MO;
            }
            prod *= INV_FFT_RATIOS[__builtin_ctz(++h)];
        }
    }
    if(m < n) {
        for(int i = 0; i < m; ++i) {
            const ui y = as[i].x + MO2 - as[i + m].x;
            as[i].x += as[i + m].x;
            as[i + m].x = y;
        }
    }
    const Mint invN = Mint(n).inv();
    for(int i = 0; i < n; ++i) {
        as[i] *= invN;
    }
}

void fft(vector<Mint> &as) {
    fft(as.data(), as.size());
}

void invFft(vector<Mint> &as) {
    invFft(as.data(), as.size());
}

vector<Mint> convolve(vector<Mint>& as, vector<Mint>& bs) {
    if(as.empty() || bs.empty()) return {};
    const int len = as.size() + bs.size() - 1;
    int n = 1;
    for(; n < len; n <<= 1) {}
    as.resize(n); fft(as);
    bs.resize(n); fft(bs);
    for(int i = 0; i < n; ++i) as[i] *= bs[i];
    invFft(as);
    as.resize(len);
    return as;
}

const int M = (int)5e5;
const int N = (int)1e5;
const int S = (int)1e6;
const int inf = 0x3f3f3f3f;
const ll mod = (ll)998244353;

int fac[M + 5], inv[M + 5], invfac[M + 5];

void init()
{
    fac[0] = fac[1] = inv[1] = invfac[0] = invfac[1] = 1;
    for(int i = 2; i <= M; ++i)
    {
        fac[i] = 1ll * fac[i - 1] * i % mod;
        inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;
        invfac[i] = 1ll * invfac[i - 1] * inv[i] % mod;
    }
}

vector<Mint> as, bs;

ll quick(ll a, ll b, ll p = mod)
{
    ll s = 1;
    while(b)
    {
        if(b & 1) s = s * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return s % p;
}

void work()
{
    int n; read(n);
    int ans = 1;
    as.resize(S + 1), bs.resize(S + 1);
    for(int i = 1, a; i <= n; ++i)
    {
        read(a);
        as[a] = 1, bs[S - a] = 1;
        ans = 1ll * ans * (a + 1) % mod * invfac[i] % mod;
    }
    convolve(as, bs);
    int k = as.size();
    for(int i = S + 1; i < k; ++i) if(as[i].x) ans = 1ll * ans * quick(i - S, as[i].x) % mod;
    print(ans, '\n');
}

int main()
{
//    ios::sync_with_stdio(0);
//    cin.tie(0); cout.tie(0);
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
//    int T; read(T);
//    for(int ca = 1; ca <= T; ++ca)
//    {
//        work();
//    }
    init();
    work();
//    cerr << 1.0 * clock() / CLOCKS_PER_SEC << "\n";
    return 0;
}
斐讯官改-K2P-A1-A2-V2.2 去后门 去除在线更新自制官改固件的功能,更加入锐捷认证功能,方便大学用户使用 增加KMS服务,广告屏蔽,Ngrok内网穿透,锐捷认证,Dr.com等 立即下载

相关推荐

Android MediaCodec学习笔记

模块介绍 基本概念 OpenMAX是Khronos Group提出的标准,目标在于创造一个统一的接口,加速大量多媒体资料的处理。OpenMAX分成三层:应用层(Application Layer, AL), 整合层(Integration Layer, IL) 以及开发层(Development Layer, DL)。 OpenMAX (Open Media Acceleration) OpenMAX AL Application Layer ..

kisshine 2358

【2022国赛模拟】无损加密——LGV引理、状压DP

被新闻搞得不想写题🙁

偶耶的博客 993

a股level2数据接口的最优委托信息

Level-1提供的数据并不可以知道委托了xxx手是有多少人下的,以及每个人下了多少的明细。通过Level-2的这个详细买卖盘数据,盘口上的单子到底是散户小打小闹,还是主力真刀实枪在干,都一览无余。交易类型:1-市价,2-限价,3-本方优先,10-撤单, 11-暂不清楚( 基金/ 债券有此值)除了提供逐笔成交记录这个信息外,还提供了最优委托信息,也就是盘口中前50笔订单的委托数量明细。那么Level-2盘口委托数据的速度更新是非常快的,大家可以通过。交易方向:0-未知,1-买入,2-卖出。

Qq_2037696191的博客 1168

LGV引理

Link 假设起点集为SSS,顶点集为TTT,求矩阵中S到T的不相交路径的方案数。 结论: LGV说白了就是解行列式的值,e(ai,bi)e(ai,bi)e(ai,bi)代表方格中ai到bi的走法,由于小学数学问题显然可以用组合数知道 e(ai,bi)=C(a到b的总步数,a到b行走的数量)e(ai,bi)=C(a到b的总步数,a到b行走的数量)e(ai,bi)=C(a到b的总步数,a到b行走的数量) [e(a1,b1)e(a1,b2)e(a1,b3)e(a2,b1)e(a2,b2)e(a2,b3)e(a3

goto_1600的博客 990

STM32F103电压采集proteus仿真

基于HAL库,仿真单片机型号为stm32f103R6,代码keil5。通过单片机的ADC采集功能,测量四路电压,数据经由DMA传输,并将结果通过串口输出,结果比较确,误差在0.01V左右。目前仿真采集四路比较稳定,多了会乱码。proteus版本8.11安装包链接:https://pan.baidu.com/s/1yhNKLl1lGSU9KU0tTuAxcg?pwd=dxe8提取码:dxe8项目下载地址:.

weixin_42490599的博客 4768

从IR Drop到EM分析:数字IC电源规划中那些没人明说的细节(以MTCMOS配置为例)

本文深入探讨数字IC后端设计中电源规划的关键细节,特别关注MTCMOS配置、电源网络电阻最小化和level shifter供电等实战技巧。通过分析IR Drop和EM问题,提供优化floorplan和powerplan的具体策略,帮助工程师避免常见陷阱,提升芯片设计的稳定性和可靠性。

q9w8e7r6t5的博客 511

CF348D LGV引理

题意: 给定一张图,图上存在障碍点,两个人从(1,1)(1,1)(1,1)出发,只能向上或向右走,走到(n,m)(n,m)(n,m)且路径不相交的方案数 数据范围:1≤n,m≤30001\le n,m\le 30001≤n,m≤3000 分析: 没什么好分析的,就是个裸题 前置芝士:LGV引理 LGVLGVLGV引理就是求解nnn组一一对应的起点到终点,且路径不相交的方案数 不会可以戳这里 题目可以转化成2个起点:(1,2),(2,1)(1,2),(2,1)(1,2),(2,1) 到 两个终点: (n,m−

youth518的博客 463

openbmc 支持mctp over pcie(二)

本文介绍了在OpenBMC系统中实现MCTP over PCIe的社区方案,主要针对AMD CPU和Intel CPU平台。方案基于社区开发的mctpd应用层和内核驱动,通过修改设备树(dts)配置内存区域,并编译Linux内核模块。验证时可通过查看/proc/net/protocols确认MCTP协议支持,使用ip addr命令检查mctppci0网络接口状态。相关代码和文档参考了AspeedTech和CodeConstruct的GitHub仓库。该方案为BMC作为MCTP端点提供了标准化实现方法。

wit_yuan的专栏 378

2021牛客暑期多校训练营9 C Cells ntt+行列式+lgv引理

题意 n个块在(0,ai)(0,a_i)(0,ai​)的位置,问有多少种方案,使得块到达(i,0)(i,0)(i,0)的不同方案数。块只能向右向下移动,两个块的路径不能相交。 分析 根据LGVLGVLGV引理,得到如下行列式AAA,行列式的值就是不想交路径的个数。 ∣Ca1+11Ca1+22...Ca1+nnCa2+11Ca2+22...Ca2+nn......Can+11Can+22...Can+nn∣ \left|\begin{array}{cccc} C_{a_1+1}^1 &

weixin_45765224的博客 326

儿童启蒙教育APP

pinyinList.add(createPinyin("a", "啊,像阿姨的阿", R.raw.pinyin_a));pinyinList.add(createPinyin("i", "衣,像衣服的衣", R.raw.pinyin_i));pinyinList.add(createPinyin("u", "乌,像乌鸦的乌", R.raw.pinyin_u));pinyinList.add(createPinyin("ü", "鱼,像小鱼的鱼", R.raw.pinyin_v));-- 固定竖屏 -->

寒寒豆豆软件公司的博客 168

Qt软件开发-Qt编译zlib完成文件压缩解压(win10)

在软件开发中进行有需求需要将生成的一些文件打包上传到服务器,或者从服务器下载压缩包下来内部解压。或者自己做一些打包工具,那么使用zlib开源就可以很方便的完成。接下来介绍在zlib在windows下如何利用Qt进行编译,调用,介绍mingw、msvc,32/64位编译办法,完成zip文件打包生成例子。可以单文件压缩打包,多文件压缩打包,目录压缩打包等等。

2217

2021牛客暑期多校训练营9C-Cells【LGV引理,范德蒙德行列式】

正题 题目链接:https://ac.nowcoder.com/acm/contest/11260/C 题目大意 一个平面上,nnn个起点(0,ai)(0,a_i)(0,ai​)分别对应终点(i,0)(i,0)(i,0),每次只能往上或者往左走。求不交路径数。 1≤n≤5×105,ai<ai+1,an≤1061\leq n\leq 5\times 10^5,a_i<a_{i+1},a_n\leq 10^61≤n≤5×105,ai​<ai+1​,an​≤106 解题思路 看起来很LGVL

QuantAsk 630

【异常】Milvus 向量数据库字段缺失错误分析与解决 MilvusVectorStoreServiceV2 - Failed to insert batch [0-1]: The field:

本文分析了Milvus向量数据库插入操作中出现的字段缺失错误。错误显示age_mode字段未提供,导致批量插入失败。根本原因是Milvus Schema要求所有定义字段必须存在,但代码中对部分字段采用条件添加方式。解决方案是将条件添加改为始终添加,为可能为null的字段提供空字符串默认值。文章总结了Schema约束、防御性编程等经验,并建议通过Schema变更检查、单元测试覆盖和数据校验层等预防措施避免类似问题。该问题影响product、mac、source等多个字段,修改后确保了数据插入的可靠性。

奶爸的编程之路,也就一周冷个三天 409

2021牛客暑期多校训练营9 Cells(LGV引理,FFT)

2021牛客暑期多校训练营9 Cells(LGV引理,FFT) 题目链接 题意 在一个无限大的xyxyxy​坐标轴上,求从A={(0,a1),(0,a2),...,(0,an)}A=\{(0,a_1),(0,a_2),...,(0,a_n)\}A={(0,a1​),(0,a2​),...,(0,an​)}​分别到B={(1,0),(2,0),...,(n,0)}B=\{(1,0),(2,0),...,(n,0)\}B={(1,0),(2,0),...,(n,0)}​​,不相交路径的方案数。 并且对于每个点A

Moyan的博客 419

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

香港 三星 android6.0,【极光ROM】-【三星NOTE20高通全系列(国行/港版/台版/韩版/美版) N98XX】-【V6.0 Android-R-UC1】...

● 支持机型:● NOTE20系列国行/港版/台版(N9810/N9860)● NOTE20系列韩版(N981N/N986N)● NOTE20系列美版(N981U/N986U)● 写在前面:1、刷机以后可能出现的问题:安全性降低、失去保修、KNOX物理熔断、无法使用三星PAY、无法支持支付宝指纹、无法连接三星手表等问题。2、刷机后开机会提示红字,感叹号(猎户目前可以修复此问题)。3、ROM中不包含...

weixin_33001561的博客 2261

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

调通sina33下的AP6212A0版本的BT(V1.0)

调通sina33下的AP6212A0版本的BT 大文实验室/大文哥 壹捌陆捌零陆捌捌陆捌贰 wb4916 AT qq.com 完成时间:2017/6/26 11:01 版本:V1.0 本文参照: 《A33 wifi移植说明书.pdf》 还有就是全志R16的parrotv1.1的官方SDK(Android4.4.2) 1、打开AP62

南岭笑笑生之家 3960

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

a28.ansible 生产实战案例 -- 基于kubeadm安装kubernetes v1.20 -- 集群升级(二)

19.k8s升级 19.1 master 19.1.1 升级master [root@ansible-server ansible]# mkdir -p roles/kubeadm-master-update/{tasks,vars} [root@ansible-server ansible]# cd roles/kubeadm-master-update/ [root@ansible-server kubeadm-master-update]# ls files tasks vars #下面HARB

Raymond的博客 311

牛客多校9-C Cells (LGV引理+线代+NTT)

题目 https://ac.nowcoder.com/acm/contest/11260/C 分析 (截图题解的,在推了……) 答案就是这三部分乘起来,前两部分好说,最后那部分,注意到值域比较小,于是统计一下在数组 a[] 中每种数的个数,然后正着一个生成函数,倒着一个生成函数,相乘,得到的系数就是差是某个数对应的 a[i]-a[j] 数量,然后乘出来就行。 时间复杂度是 O(n lgn) 的。 代码 #include <bits/stdc++.h> using namespace std;

hehepig的博客 290

2018牛客多校第一场 Monotonic Matrix (LGV引理)

链接:https://www.nowcoder.com/acm/contest/139/A来源:牛客网 题目描述 Count the number of n x m matrices A satisfying the following condition modulo (109+7). * Ai, j ∈ {0, 1, 2} for all 1 ≤ i ≤ n, 1 ≤ j ...

weixin_30297281的博客 299

Google Earth Engine ——MOD16A2 V105产品以1公里的像素分辨率提供8天的全球陆地蒸发量(ET)信息

The MOD16A2 V105 product provides information about 8-day global terrestrial evapotranspiration at 1km pixel resolution. Evapotranspiration (ET) is the sum of evaporation and plant transpiration from the Earth's surface to the atmosphere. With long-term ET

此星光明博客 2484

以后能用的着

  论文网[http://www.51lw.com(免费论文下载)  论 文 帝国[http://www.papersempire.com(论文资源) 论 文 资料网[http://www.51paper.net(各专业论文下载) 论 文 快车网[http://www.lun-wen.com(各专业论文下载) 毕 业 论文网[http://www.bylw.com(论文

子墨 780

The 2021 ICPC Asia Regionals Online Contest (II)【解题报告】

戳我进入比赛 Problem A. Sort 题目大意 TTT 组,每组给出一个长度为 nnn 的序列 a[]a[]a[] 和 整数 kkk. 定义一次操作为将序列 a[]a[]a[] 分割成 viv_ivi​ 段,再对段做置换 pip_ipi​. 若在有限次数操作中,无法使得序列 a[]a[]a[] 变成非降序,则输出 −2-2−2. 若在有限次数操作中,可以使得序列 a[]a[]a[] 变成非降序,且 ∑vi≤3n\sum{v_i} \leq 3n∑vi​≤3n,则输出方案,否则输出 −1-1−1.

The___Flash的博客 1965

2020ICPC·小米 网络选拔赛第一场

先贴一份代码,之后再来写~~(咕)~~ A Intelligent Warehouse 三.代码实现 #include <bits/stdc++.h> using namespace std; typedef long long ll; const int M = (int)2e5; const int N = (int)1e7; const double eps = 1e-9; const int inf = 0x3f3f3f3f; const ll mod = (ll)998244353

The___Flash的博客 1281

SDNU_ACM_ICPC_2020_Winter_Practice

VJudge: SDNU_ACM_ICPC_2020_Winter_Practice_1st SDNU_ACM_ICPC_2020_Winter_Practice_2nd SDNU_ACM_ICPC_2020_Winter_Practice_3rd SDNU_ACM_ICPC_2020_Winter_Practice_4th 牛客: SDNU_ACM_ICPC_2020_Winter_...

The___Flash的博客 1187

2022牛客寒假算法基础集训营4【解题报告】

戳我进入比赛 Problem A. R 题目大意 输入两个整数 n,kn,kn,k 和一个长度为 nnn 的字符串 sss. 问字符串 sss 中存在多少个子串满足该子串至少包含 kkk 个 ′R′'R'′R′ 字符,且不包含 ′P′'P'′P′ 字符. 1≤n≤2×105,1≤k≤20,s[i]∈{′A′−′Z′}1 \leq n \leq 2 \times 10^5, 1 \leq k \leq 20, s[i] \in \{'A'-'Z'\}1≤n≤2×105,1≤k≤20,s[i]∈{′A′−′Z

The___Flash的博客 987

SDNU ACM-ICPC 2020 Freshman‘s first monthly competition(11-15)【解题报告】

题解 说明 以下内容为现场赛时写的,一边看榜,一边写,所以是按照每道题被拿走FB的顺序写的。 1616.Arithmetic Sequence[签到] 出题人:ymf 验题人:李浩然、王欣、蓝宗慰 全场最简单的题目,于 00:02:57 被 2020Wangweiyi 拿走全场 First Blood! 题目大意 \quad给出一个整数 SSS,要求你构造一个长度最短的等差数列,使其和为 SSS. 分析 \quad直接输出 SSS 不就好啦. 代码实现 #include <bits/stdc++.h&

The___Flash的博客 939
上一篇: The 2021 ICPC Asia Regionals Online Contest (II)【解题报告】
下一篇: 我想起那天在夕阳下的口胡,那是我逝去的青春。
The___Flash
博客等级 码龄8年 79粉丝 223原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值