AGC053C Random Card Game【概率,分析性质】

给定编号为 (1,2,cdots,2n)(2n) 张卡片,首先将其随机打乱成两堆,各 (n) 张卡片。你每次操作选择不超过两堆卡片数的正整数 (k),比较两堆的第 (k) 张卡片的编号大小,将较小的扔掉。求操作数最小值的期望值(mod(10^9+7))

(nle 10^6)


不妨设 (2n) 在牌堆 (B) 中,则最后的目标是将 (A) 删空。

结论:设 (d=maxlimits_{i=1}^nmin{j-imid A_i<B_j}),则答案为 (n+d)

证明:首先答案 (ge n+d),因为在删去 (A_i) 之前一定要把 (B_i,B_{i+1},cdots,B_{j-1}) 都删掉。并且操作次数可以取到 (n+d):若当前 (d=0) 则每次选最大的 (i) 使得 (A_i<B_i),将 (A_i) 删掉,否则选择最小的 (i) 使得 (min{j-imid A_i<B_j}=d) 然后将 (B_i) 删掉。

然后要计算期望。由于 (d)(max) 的形式,考虑设 (p(d)) 表示答案 (le n+d) 的概率,则答案为 (2n-sum_{i=0}^{n-1}p(i))

考虑计算 (p(d)),要求满足的条件即为 (B_1,B_2,cdots,B_{min{n,i+d}}) 中至少有一个 (>A_i)

按从后往前的顺序确定 (A_i),要求 (A_1,A_2,cdots,A_{i-1},B_1,B_2,cdots,B_{min{n,i+d}}) 至少有一个 (>A_i),此时每一步独立,把概率乘起来就得到:

[p(d)=2prod_{i=1}^{n-d}frac{2i+d-1}{2i+d}prod_{i=n-d+1}^nfrac{n+i-1}{n+i}=frac{(d+1)cdots(2n-d-1)}{n(d+2)cdots(2n-d-2)} ]

预处理双阶乘及其逆元就可以 (O(n)) 算答案啦:)

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e6 + 5, mod = 1e9 + 7;
int n, fac[N], inv[N], ans;
int ksm(int a, int b){
    int res = 1;
    for(;b;b >>= 1, a = (LL)a * a % mod)
        if(b & 1) res = (LL)res * a % mod;
    return res;
} void qmo(int &x){x += x >> 31 & mod;}
void init(int m){
    fac[0] = fac[1] = 1;
    for(int i = 2;i <= m;++ i)
        fac[i] = (LL)fac[i-2] * i % mod;
    inv[m] = ksm(fac[m], mod-2);
    inv[m-1] = ksm(fac[m-1], mod-2);
    for(int i = m;i >= 2;-- i)
        inv[i-2] = (LL)inv[i] * i % mod;
}
int main(){
    scanf("%d", &n); init(n<<1); ans = (LL)fac[(n<<1)-1] * inv[n-1<<1] % mod;
    for(int d = 1;d < n;++ d)
        ans = (ans + (LL)fac[(n<<1)-d-1] * inv[(n-1<<1)-d] % mod * inv[d-1] % mod * fac[d]) % mod;
    qmo(ans = 2*n - (LL)ans * ksm(n, mod-2) % mod); printf("%d
", ans);
}
原文地址:https://www.cnblogs.com/AThousandMoons/p/14685873.html