AGC053C
先考虑两个牌堆固定了的话,最小操作次数是什么。
不妨假设两个牌堆为 \(A,B\),并且 \(2n\) 在牌堆 \(B\) 中,则最后的目标是将 \(A\) 删空。
结论:设 \(d=\max\limits_{i=1}^{n}\min\left\{j-i\mid A_i\lt B_j\right\}\),则答案为 \(n+d\)。
证明:首先答案显然不小于 \(n+d\),因为在删去 \(A_i\) 之前一定要把 \(B_i,B_{i+1},\cdots,B_{j-1}\) 删去,现在来证明可以取到 \(n+d\)。
若当前 \(d\gt 0\),选择最小的 \(i\) 使得 \(\min\left\{j-i\mid A_i\lt B_j\right\}=d\) 然后将 \(B_i\) 删掉,发现这样能使 \(d\gets d-1\)。否则若当前 \(d=0\),选择最大的 \(i\) 使得 \(A_i\lt B_i\),将 \(A_i\) 删去。
考虑设 \(p(d)\) 表示答案不大于 \(n+d\) 的概率,则答案为 \(2n-\sum_{d=0}^{n-1}p(d)\)。
考虑计算 \(p(d)\),要求满足的条件即为对于所有的 \(i\),\(B_1,B_2,\cdots,B_{\min(n,i+d)}\) 至少有一个大于 \(A_i\)。
考虑依次填入 \(A_n,A_{n-1},\cdots,A_{n-d+1}\),然后轮流填入 \(B_{n-i},A_{n-d-i}\),最后填入 \(B_d,B_{d-1},\cdots,B_{1}\)。
为什么这样填,因为这样构造之后每次填 \(A\) 只要满足不填入当前最大值即可,而填 \(B\) 则没有任何限制。
综上所述:\(p(d)=2\prod\limits_{i=1}^{n-d}\dfrac{2i+d-1}{2i+d}\prod\limits_{i=n-d+1}^{n}\dfrac{n+i-1}{n+i}=\dfrac{(d+1)\times (d+3)\times \cdots \times (2n-d-1)}{n(d+2)\times (d+4)\times \cdots \times (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;
}