AGC053C
先考虑两个牌堆固定了的话,最小操作次数是什么。
不妨假设两个牌堆为 A,B,并且 2n 在牌堆 B 中,则最后的目标是将 A 删空。
结论:设 d=nmaxi=1min{j−i∣Ai<Bj},则答案为 n+d。
证明:首先答案显然不小于 n+d,因为在删去 Ai 之前一定要把 Bi,Bi+1,⋯,Bj−1 删去,现在来证明可以取到 n+d。
若当前 d>0,选择最小的 i 使得 min{j−i∣Ai<Bj}=d 然后将 Bi 删掉,发现这样能使 d←d−1。否则若当前 d=0,选择最大的 i 使得 Ai<Bi,将 Ai 删去。
考虑设 p(d) 表示答案不大于 n+d 的概率,则答案为 2n−∑n−1d=0p(d)。
考虑计算 p(d),要求满足的条件即为对于所有的 i,B1,B2,⋯,Bmin(n,i+d) 至少有一个大于 Ai。
考虑依次填入 An,An−1,⋯,An−d+1,然后轮流填入 Bn−i,An−d−i,最后填入 Bd,Bd−1,⋯,B1。
为什么这样填,因为这样构造之后每次填 A 只要满足不填入当前最大值即可,而填 B 则没有任何限制。
综上所述:p(d)=2n−d∏i=12i+d−12i+dn∏i=n−d+1n+i−1n+i=(d+1)×(d+3)×⋯×(2n−d−1)n(d+2)×(d+4)×⋯×(2n−d−2)。
简单预处理前缀积和逆元即可。
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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效