ARC138E

给定正整数 n,k,对于一个长为 n 的序列 {ai},我们称其是好的当且仅当:

  1. i,1in,均满足 0aii
  2. v=1,2,,n,至多有一个下标 i 满足 ai=v

求所有好序列中长为 k 的严格递减子序列的出现次数之和,答案对 109+7 取模。

第一步是巧妙的转化:对于 ai>0,连边 iai1
对于每个好的序列 a,连边后形成若干条链
假设选出的 k 个点为 b1,b2,,bk,并且 b1<b2<<bk,对应的 ab11,,abk1 为了方便记作 c1,c2,,ck,则有:
ck<ck1<<c1<b1<b2<<bk
这可以由 b1>c1c 递减,b 递增推导出来。
也就是说,对于确定的 a,在 [0,n] 中选出 2k 个点,它们对应的子序列有且仅有一种
注意到这 k 条边一定恰好涉及到 k 条链,先删去这 k 条边,将其中不超过 c1 的点集记为 A,不小于 b1 的点集记为 B
那么我们要计算分别将 A,B 拆成 k 条链的方案数。注意,一旦两边拆出 k 条链的方案确定了,连 k 条边的方案也就唯一确定了。
考虑枚举前 k 个点以及所在链上的其他点的个数 i,后 k 个点以及所在链上的其他点的个数 j,则方案数为:
(n+1i+j){ik}{jk}n+1ijx=1{n+1ijx}
i 个点分成 j 条链的方案数等价于第二类斯特林数,因为链上总是编号大的指向编号小的。
注意到 n+1ijx=1{n+1ijx} 其实就是贝尔数 Bn+1ij
上面这些组合数,斯特林数,贝尔数都可以 O(n2) 预处理出来。

Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5005, mod = 1e9 + 7;
int n, k;
int fac[N], inv[N];
int S[N][N], B[N];

int qpow(int x, int y) {
	int res = 1;
	while (y) {
		if (y & 1) res = 1ll * res * x % mod;
		x = 1ll * x * x % mod;
		y >>= 1;
	}
	return res;
}

void init(int n) {
	fac[0] = 1;
	for (int i = 1; i <= n; ++i) fac[i] = 1ll * fac[i - 1] * i % mod;
	inv[n] = qpow(fac[n], mod - 2);
	for (int i = n - 1; ~i; --i) inv[i] = 1ll * inv[i + 1] * (i + 1) % mod;
	S[0][0] = 1;
	for (int i = 1; i <= n; ++i) {
		S[i][1] = S[i][i] = 1;
		for (int j = 2; j < i; ++j)
			S[i][j] = (S[i - 1][j - 1] + 1ll * S[i - 1][j] * j % mod) % mod;
	}
	for (int i = 0; i <= n; ++i) {
		for (int j = 0; j <= i; ++j) B[i] = (B[i] + S[i][j]) % mod;
	}
}

int C(int n, int m) {
	if (n < 0 || m < 0 || n < m) return 0;
	return 1ll * fac[n] * inv[n - m] % mod * inv[m] % mod;
}

int main() {
	scanf("%d%d", &n, &k);
	init(n + 1);
	int ans = 0;
	for (int i = k; i <= n + 1; ++i)
		for (int j = k; j <= n + 1 - i; ++j) {
			int tmp = C(n + 1, i + j);
			tmp = 1ll * tmp * S[i][k] % mod;
			tmp = 1ll * tmp * S[j][k] % mod;
			tmp = 1ll * tmp * B[n + 1 - (i + j)] % mod;
			ans = (ans + tmp) % mod;
		}
	printf("%d", ans);
	return 0;
}
posted @   Kobe303  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示