AGC053C

先考虑两个牌堆固定了的话,最小操作次数是什么。
不妨假设两个牌堆为 A,B,并且 2n 在牌堆 B 中,则最后的目标是将 A 删空。
结论:设 d=nmaxi=1min{jiAi<Bj},则答案为 n+d
证明:首先答案显然不小于 n+d,因为在删去 Ai 之前一定要把 Bi,Bi+1,,Bj1 删去,现在来证明可以取到 n+d
若当前 d>0,选择最小的 i 使得 min{jiAi<Bj}=d 然后将 Bi 删掉,发现这样能使 dd1。否则若当前 d=0,选择最大的 i 使得 Ai<Bi,将 Ai 删去。
考虑设 p(d) 表示答案不大于 n+d 的概率,则答案为 2nn1d=0p(d)
考虑计算 p(d),要求满足的条件即为对于所有的 iB1,B2,,Bmin(n,i+d) 至少有一个大于 Ai
考虑依次填入 An,An1,,And+1,然后轮流填入 Bni,Andi,最后填入 Bd,Bd1,,B1
为什么这样填,因为这样构造之后每次填 A 只要满足不填入当前最大值即可,而填 B 则没有任何限制。
综上所述:p(d)=2ndi=12i+d12i+dni=nd+1n+i1n+i=(d+1)×(d+3)××(2nd1)n(d+2)×(d+4)××(2nd2)
简单预处理前缀积和逆元即可。

Code:

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

void add(int &a, int b) {
	a += b;
	if (a >= mod) a -= mod;
}

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] = fac[1] = 1;
	for (int i = 2; i <= n; ++i) fac[i] = 1ll * fac[i - 2] * i % mod;
	inv[n] = qpow(fac[n], mod - 2);
	inv[n - 1] = qpow(fac[n - 1], mod - 2);
	for (int i = n; i >= 2; --i) inv[i - 2] = 1ll * inv[i] * i % mod;
}

int main() {
	scanf("%d", &n), init(n * 2);
	ans = 1ll * fac[n * 2 - 1] * inv[n * 2 - 2] % mod;
	for (int d = 1; d < n; ++d) add(ans, 1ll * fac[n * 2 - d - 1] * inv[d - 1] % mod * inv[n * 2 - d - 2] % mod * fac[d] % mod);
	ans = n * 2 - 1ll * ans * qpow(n, mod - 2) % mod;
	if (ans < 0) ans += mod;
	printf("%d", ans);
	return 0;
}
posted @   Kobe303  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示