[题解]可恶!然而......

\[\color{red}{\text{校长者,真神人也,左马桶,右永神,会执利笔破邪炁,何人当之?}} \\ \begin{array}{|} \hline \color{pink}{\text{The principal is really a god}} \\ \color{pink}{\text{with a closestool on the left and Yongshen on the right}} \\ \color{pink}{\text{holding a sharp pen to pierce the truth}} \\ \color{pink}{\text{Who can resist him? }} \\ \hline \end{array} \\ \begin{array}{|} \hline \color{green}{\text{校長は本当に神であり、左側にトイレ、右側にヨンシェンがあり}} \\ \color{green}{\text{鋭いペンを持って真実を突き刺している。誰が彼に抵抗できるだろうか? }} \\ \hline \end{array} \\ \begin{array}{|} \hline \color{lightblue}{\text{Le principal est vraiment un dieu}} \\ \color{lightblue}{\text{avec des toilettes à gauche et Yongshen à droite}} \\ \color{lightblue}{\text{tenant un stylo pointu pour percer la vérité}} \\ \color{lightblue}{\text{Qui peut lui résister ? }} \\ \hline \end{array} \\ \begin{array}{|} \hline \color{purple}{\text{Der Direktor ist wirklich ein Gott}} \\ \color{purple}{\text{mit einer Toilette links und Yongshen rechts}} \\ \color{purple}{\text{der einen spitzen Stift hält}} \\ \color{purple}{\text{um die Wahrheit zu durchdringen.}} \\ \color{purple}{\text{Wer kann ihm widerstehen? }} \\ \hline \end{array} \\ \begin{array}{|} \hline \color{cyan}{\text{Principalis deus est, Yongshen a dextris cum latrina}} \\ \color{cyan}{\text{acuto stylo ad perforandum veritatem: quis resistet ei? }} \\ \hline \end{array} \\ \color{red}{\text{对曰:“无人,狗欲当之,还请赐教!”}} \\ \newcommand\brak[1]{\left({#1}\right)} \newcommand\Brak[1]{\left\{{#1}\right\}} \newcommand\d[0]{\text{d}} \newcommand\string[2]{\genfrac{\{}{\}}{0pt}{}{#1}{#2}} \newcommand\down[2]{{#1}^{\underline{#2}}} \newcommand\ddiv[2]{\left\lfloor\frac{#1}{#2}\right\rfloor} \newcommand\udiv[2]{\left\lceil\frac{#1}{#2}\right\rceil} \newcommand\lcm[0]{\operatorname{lcm}} \newcommand\set[1]{\left\{{#1}\right\}} \newcommand\ceil[1]{\left\lceil{#1}\right\rceil} \newcommand\floor[1]{\left\lfloor{#1}\right\rfloor} \newcommand\rhs[1]{\;\text{Rhs}\;#1} \newcommand\lhs[1]{\;\text{Lhs}\;#1} \newcommand\Vec[1]{\vec{\mathbf{#1}}} \newcommand\rank[0]{\text{rank}} \]




  \(\mathcal{Back\;To\;The\;Menu}\).

2022-02-26 可恶!然而......

  卡在一道从未想过的题上面......

排队 / Queue

  设 \(d(i)\) 表示 \(\sum_{j<i}[a_j>a_i]\),就是反序表那玩意,然后我们想求满足 \(\sum_id(i)=\sum_i\max(i-a_i,0)\) 的序列个数。

  就每个位置而言,显然存在 \(d(i)\ge \max(i-a_i,0)\),因为 \(i-a_i\) 表示至少有多少个比它大的在它前面,而 \(d(i)\) 表示准确的比它大且在它前面的数字个数。因此,想让 \(\sum_id(i)=\sum_i\max(i-a_i,0)\) 成立,无非让每个位置都要满足 \(d(i)=\max(i-a_i,0)\),这个等式意味着什么?要么前面没有比它大的,要么所有比它小的都在它前面.

   此时我们可以使用 DP,每增加一个位置,只可能有两种选择:填入比最大值还要大的数(前面没有比它大的),或者是前缀集合的 mex(不能算上 \(0\)),设 \(f(i,j)\) 表示前 \(i\) 个位置,最大值为 \(j\),存在转移:

\[f(i,j)=f(i-1,j)+\sum_{k<j}f(i-1,k) \\ f(i,j)=0\qquad(i>j) \]

  它是一个前缀和的形式,记 \(g(i,j)=\sum_{k\le i}f(i,k)\),那么

\[g(i,j)=\sum_{k\le j}f(i,k)=\sum_{k\le j}\brak{f(i-1,k)+\sum_{t<k}f(i-1,t)}=\sum_{k\le j}g(i-1,k)=g(i,j-1)+g(i-1,j) \]

  发现最后我们将形式统一到了一个类似于网格图上走路的问题,每次可以向右或者向上走一步,最后走到 \((n,n)\) 的方案数,但是还有一个问题,当 \(i>j\) 时,\(g\) 实际上是不参与转移的,也就是说,我们中途还不能逾越 \(y=x\) 这条线,于是这就变成经典的卡塔兰数模型了,从输入的 \(m\) 个数中,我们可以得到最大值 \(\max\),最后就是算从 \((m,\max)\to (n,n)\) 中途不逾越 \(y=x\) 的方案数了。

/** @author __Elaina__ */

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

// #define USING_FREAD
// #define NDEBUG
#include <cassert>

namespace Elaina {
/** その可憐な少女は魔女であり、旅人でした。 ―― そう、私です! */

#define rep(i, l, r) for (int i = (l), i##_end_ = (r); i <= i##_end_; ++i)
#define drep(i, l, r) for (int i = (l), i##_end_ = (r); i >= i##_end_; --i)
#define fi first
#define se second
#define mp(a, b) make_pair(a, b)
#define Endl putchar('\n')
#define whole(v) ((v).begin()), ((v).end())
#define bitcnt(s) (__builtin_popcount(s))
/** @warning no forced type conversion */
#define rqr(x) ((x) * (x))
#define y0 FUCK_UP
#define y1 MOTHER_FUCKER

typedef long long ll;
typedef unsigned long long ull;
typedef std::pair<int, int> pii;

template <class T>
inline T fab(T x) {
    return x < 0 ? -x : x;
}
template <class T>
inline void chkmin(T& x, const T rhs) {
    x = std::min(x, rhs);
}
template <class T>
inline void chkmax(T& x, const T rhs) {
    x = std::max(x, rhs);
}

#ifdef USING_FREAD
inline char qkgetc() {
#define BUFFERSIZE 1 << 20
    static char BUF[BUFFERSIZE], *p1 = BUF, *p2 = BUF;
    return p1 == p2 && (p2 = (p1 = BUF) + fread(BUF, 1, BUFFERSIZE, stdin), p1 == p2) ? EOF : *p1++;
#undef BUFFERSIZE
}
#define CHARRECEI qkgetc()
#else
#define CHARRECEI getchar()
#endif

template <class T>
inline T readret(T x) {
    x = 0;
    int f = 0;
    char c;
    while (!isdigit(c = CHARRECEI))
        if (c == '-')
            f = 1;
    for (x = (c ^ 48); isdigit(c = CHARRECEI); x = (x << 1) + (x << 3) + (c ^ 48))
        ;
    return f ? -x : x;
}
template <class T>
inline void readin(T& x) {
    x = 0;
    int f = 0;
    char c;
    while (!isdigit(c = CHARRECEI))
        if (c == '-')
            f = 1;
    for (x = (c ^ 48); isdigit(c = CHARRECEI); x = (x << 1) + (x << 3) + (c ^ 48))
        ;
    if (f)
        x = -x;
}
template <class T, class... Args>
inline void readin(T& x, Args&... args) {
    readin(x), readin(args...);
}
template <class T>
inline void writln(T x, char c = '\n') {
    if (x < 0)
        putchar('-'), x = -x;
    static int __stk[55], __bit = 0;
    do
        __stk[++__bit] = x % 10, x /= 10;
    while (x);
    while (__bit) putchar(__stk[__bit--] ^ 48);
    putchar(c);
}

}  // namespace Elaina
using namespace Elaina;

const int Maxn = 1e5 * 2;
const int Mod = 1e9 + 7;

int inv[Maxn + 5], fac[Maxn + 5], finv[Maxn + 5];
inline void prelude() {
    fac[0] = inv[0] = fac[1] = inv[1] = finv[0] = finv[1] = 1;
    rep(i, 2, Maxn) {
        fac[i] = 1ll * fac[i - 1] * i % Mod;
        inv[i] = 1ll * (Mod - Mod / i) * inv[Mod % i] % Mod;
        finv[i] = 1ll * finv[i - 1] * inv[i] % Mod;
    }
}
inline int C(int n, int m) {
    if (n < m || n < 0 || m < 0)
        return 0;
    return 1ll * fac[n] * finv[n - m] % Mod * finv[m] % Mod;
}
inline int Cata(int n, int m) { return (0ll + C(n + m, n) + Mod - C(n + m, m - 1)) % Mod; }

int n, m, a[Maxn + 5];

signed main() {
    freopen("queue.in", "r", stdin);
    freopen("queue.out", "w", stdout);
    prelude();
    readin(n, m);
    int tl1 = 0, tl2 = 0;
    rep(i, 1, m) {
        readin(a[i]);
        if (a[i] <= i) {
            if (a[i] < tl1)
                return writln(0), 0;
            tl1 = a[i];
        } else {
            if (a[i] < tl2)
                return writln(0), 0;
            tl2 = a[i];
        }
    }
    tl2 = min(n - tl2, n - m);
    writln(Cata(n - m, tl2));
    return 0;
}

论文查重 / Thesis

  这就是我说的那道奇怪的题......

  一般的 LCS 思路,是 DP,设 \(f(i,j)\) 表示 \(T\) 匹配到 \(i\)\(S\) 匹配到 \(j\) 时,LCS 的长度,注意到 \(|S|\) 总共很大,不妨将 \(j\) 设为状态中储存的量,而将 LCS 的长度变成状态,所以有了一个新状态:\(g(i,j)\) 表示 \(T\) 匹配到 \(i\),当前 LCS 的长度为 \(j\) 时,\(S\) 至少匹配到哪里了,然后再进行转移即可。

  仍然没有代码 😦

烽火戏诸侯 / Balefire

  永神给出了一种贪心可以过掉,但是目前为止仍然不知道应该怎么证明。

  先考虑将位置相邻的进行操作,直到无法操作为止,此时剩下的东西在坐标上应当是一个连续段,然后再考虑依次将坐标最大的和坐标和第三大、第四大、第五大......依次进行操作:

  计算一下它的贡献,就完了。

  个人感觉它是否有点像 [ARC126E]Infinite Operations 啊?

posted @ 2022-03-14 22:05  Arextre  阅读(38)  评论(0编辑  收藏  举报