AGC055C Weird LIS 构造+组合数学
\(p_i\) 被删除时有两种情况,一种 LIS 中 必定包含 \(p_i\) ,没有替代品,称为必需点。还有一种是 LIS 中不一定包含 \(p_i\),有替代品,称为非必需点。
不妨设整个序列的 LIS 为 \(K\),那么必需点的 \(A_i=K-1\),非必需点 \(A_i=K\)。分情况讨论。
-
如果 \(A\) 全部相等:
- 如果全是必需点,易得:序列为 \(\{1,2,3,...,n\}\) ,\(A_i=n-1\);
- 如果全是非必需点,因为每个点至少要有一个点和他替换,所以至多 \(\lfloor n/2\rfloor\),构造方案可以是:\(\{n-K+1,n-K+2,...,n,n-2K+1,...n-K,...\}\)。
-
如果 \(A\) 不全部相等:
设必需点对整个序列的 LIS 贡献了 \(K1\) 的长度,非必需点贡献了 \(K2\) 的长度、
考虑通过必需点将序列切开。容易发现,设非必需点段两端的必需点的值分别为 \([L,R]\),那么非必需点 \(\in [L,R]\) 时才有可能对答案有贡献。
那么我们挑出其中长度为 \(len\) 一段来看,我们考虑这一段对整个序列的 LIS 的贡献的范围。
最小值,可以把序列中最大的几个数倒序填在这一段,\(\{L,n,n-1,...,R\}\),那么贡献就会为0。
最大值,考虑每个必需点都至少有一个点和它替换,所以最大是 \(\lfloor len/2\rfloor\)。构造方案可以是 \(\{L,L+2,L+1,L+4,L+3,...,R\}\)
那么我们考虑计算 \(A\) 的种类数量。
设有 \(x\) 个必需点,\(y=\sum \lfloor len_i/2\rfloor\)。枚举 \(x,y\),考虑必需点和点对的位置关系,以及向下取整每段取掉的 \(0/1\) 个。以及最终的答案范围。
\[ans=\sum_{x=1}^{n-1} \sum_{y=0}^{\lfloor (n-x)/2\rfloor} · {x+y\choose x}{x+1\choose n-x-2y}·{(min(x+y,m)-max(3,x)+1)} \]code
#include<bits/stdc++.h> using namespace std; typedef long long ll; #define ls(x) ((x)<<1) #define rs(x) ((x)<<1|1) #define fi first #define se second #define mkp make_pair #define PII pair<ll,ll> const int N = 5010; int n, m, mod, C[N][N]; int calc(int x, int y) { //x个必需点,y个非必需点对。 return (min(x + y, m) >= max(3, x)) ? (1ll * C[x + y][x] * C[x + 1][n - x - 2 * y] % mod * (min(x + y, m) - max(3, x) + 1) % mod) : 0; } int main() { scanf("%d%d%d", &n, &m, &mod); C[0][0] = 1; for(int i = 1; i <= n; i++) { C[i][0] = 1; for(int j = 1; j <= i; j++) C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod; } int ans = min(m, n / 2) - 2 + 1 + (m == n - 1); for(int i = 1; i <= min(n - 1, m); i++) for(int j = 0; j <= (n - i) / 2; j++) ans = (ans + calc(i, j)) % mod; printf("%d\n", ans); return 0; }
QwQwQ