2025.2.17 鲜花
机关 题解
MARENOL
要是放这个歌机房会有人能欣赏吗???
来自b站视频av35346701下的评论
应该是 LeaF 本人自己写的
侵删
感觉不是难题。
题目中的 \(k\) 即 \(1\) 的位置在这里记作 \(m\)。
容易发现, \(a\) 序列一定是先单调递降到 \(1\) 在单调递增的 V 字,考虑每次弹出最前和最后,所以 \(b\) 序列在 \(1\) 之前的部分一定可以拆成两个单调递降的子序列,并且能拆的一定可以生成。
在 \(1\) 后面取出的方案数是显的,其在 \(a\) 上只有两种排列方式即单增或单降,但其是等价的,而每次只能取最前或最后,于是是 \(2 ^ {x - 1}\)(\(x\) 是剩余颜色个数)。
考虑求出 \(1\) 之前的部分,用两个序列 \(A, B\) 表示其划分成的子序列,并且 \(A\) 是拿 \(1\) 前一步拿的一边,为了不重复计算我们定义一个序列的划分是依次遍历每个值,如果能放入 \(A\) 就放入 \(A\),否则放入 \(B\),容易证明其会构成双射。
考虑计数,设 \(dp_{i,j}\) 表示当前是 \(b\) 的第 \(i\) 位,\(A\) 的最后一位是 \(j\) 的方案数,考虑转移,分讨第 \(i\) 位放到哪里了,若放到 \(A\) 则第 \(i\) 位必然填 \(j\),且可以从 \(dp_{i - 1, k}(k>j)\) 转移,若放到 \(B\) 则必然填剩余的最大的,若填较小的则更大的数就无处可去了(因为 \(1\) 右边的数一定小于 \(1\) 左边 \(B\) 中的数,而 \(B\) 又是递降的),可以从 \(dp_{i - 1, j}\) 转移过来。
于是方程就是:
注意到 \(k\) 的上节 \(l\),其并不总是 \(n\),原因是当转移 \(dp_{i, j}\) 时,一共剩下 \(n - i\) 个元素,而 \([1, j - 1]\) 是必然剩下的,否则非法,于是 \(j - 1 \le n - i\),即 \(l = n - i + 1\)。
上个前缀和就可以 \(\mathcal{O}(n ^ 2)\) 求了,容易想到放到格路上考虑。
先给一组固定的起点和终点,设 \(dp_{0, n + 1} = 1\),终点是 \(\sum\limits_{i = 2}^{n - m} dp_{m - 1,i} = dp_{m, 2}\),于是问题变成了从 \((0, n)\) 走到 \((m, 2)\),格路形如:
将其推平,最高位是不能水平向右转移的,加一条线表示永不碰到,于是就变成了:
直接卡特兰数即可,一点小问题是因为最后一行的竖线存在,答案事实上求了前缀和,可以用 \((m, 2)\) 和 \((m, 3)\) 差分一下,或者直接求到 \((m - 1, 2)\) 即可。
Code
/* Local File
in_out/in.in
in_out/out.out
*/
#include <bits/stdc++.h>
using namespace std;
using llt = long long;
using ull = unsigned long long;
using llf = long double;
#define endl '\n'
#ifndef LOCAL
#undef assert
#define assert 0 &&
#define cerr 0 && cerr
FILE *InFile = freopen("game.in", "r", stdin), *OutFile = freopen("game.out", "w", stdout);
#endif
const int N = 5e5 + 3, M = N * 2 - 3;
int n, m, MOD, ans = 0;
int aas, fac[M], ivf[M];
int Fpw(int a, int b){
if(b < 0) return 1;
int ans = 1;
while(b){
if(b & 1) ans = 1ll * ans * a % MOD;
a = 1ll * a * a % MOD, b >>= 1;
}
return ans;
}
int C(int a, int b){
return a < b ? 0 : 1ll * fac[a] * ivf[b] % MOD * ivf[a - b] % MOD;
}
int P(int a, int b, int c, int d){
int l = c - a, r = d - b;
return C(l + r, l);
}
int Cat(int a, int b, int c, int d){
return (1ll * P(a, d, c, b) - P(a, b - c + 2, n + 2 - d, b)) % MOD;
}
int main(){
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
cin >> n >> m >> MOD;
if(n == 1)
return cout << 1, 0;
fac[0] = 1;
for(int i = 1; i <= M - 3; ++i)
fac[i] = 1ll * fac[i - 1] * i % MOD;
ivf[M - 3] = Fpw(fac[M - 3], MOD - 2);
for(int i = M - 3; i; --i)
ivf[i - 1] = 1ll * ivf[i] * i % MOD;
cout << ((1ll * Cat(0, n, m, 2) - Cat(0, n, m, 3)) % MOD * Fpw(2, n - m - 1) % MOD + MOD) % MOD;
}
P
本文来自博客园,作者:xrlong,转载请注明原文链接:https://www.cnblogs.com/xrlong/p/18720687
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。