归档:220808 | 开门劝退:排列组合系列题

Codeforces [1284C] - New Year and Permutation

算一个序列中有多少个合法数对是很麻烦的,那么不妨换个角度想,对于每个数对,计算能被多少个序列包含。

容易发现对于 [l,r],设最小值为 l+v,最大值为 r+v,那么剩余的 rl1 个数既不能比 l+v 小,也不能比 r+v 大,还不能重复,那么就与 (l+v,r+v) 对应。也就是说,左端点的值确定后,区间包含元素唯一确定。

对于所有长度为 i 的区间,左端点有 ni+1 种选择,区间所在的位置有 ni+1 种选择,区间可任意排列,不影响极差,所以有 Aii 种排列方式,除该区间以外的数有 Anini 种排列方式(这一步,因为每个数列的每个合法区间都要计算,所以不用对该区间之外的合法区间去重)。

乘法原理,全部相乘即可得到长度为 i 的所有区间的答案,枚举 i,相加即可。

特别地,对于长度为 1 的区间,每个区间都被 Ann 个区间包含,共有 n×Ann 个。

namespace XSC062 {
using namespace fastIO;
const int maxn = 2.5e5 + 15;
int n, mod, ans;
int u[maxn], inv[maxn];
inline int qkp(int x, int y) {
	int res = 1;
	while (y) {
		if (y & 1)
			(res *= x) %= mod;
		(x *= x) %= mod;
		y >>= 1;
	}
	return res;
}
inline void Init(int n) {
	u[0] = 1;
	inv[0] = 1;
	for (int i = 1; i <= n; ++i) {
		u[i] = (u[i - 1] * i) % mod;
		inv[i] = qkp(u[i], mod - 2);
	}
	return;
}
inline int A(int n, int m) {
	return (u[n] * inv[n - m]) % mod;
}
int main() {
	read(n);
	read(mod);
	Init(n + 5);
	ans = (A(n, n) * n) % mod;
	for (int i = 2; i <= n; ++i) {
		(ans += (((n - i + 1) * (n - i + 1)) % mod
				* A(i, i)) % mod * A(n - i, n - i)
				% mod) %= mod;
	}
	printf("%lld", ans);
	return 0;
}
} // namespace XSC062
posted @   XSC062  阅读(33)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示