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

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

\(n\le 10^6\)


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

结论:设 \(d=\max\limits_{i=1}^n\min\{j-i\mid 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-i\mid 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)=2\prod_{i=1}^{n-d}\frac{2i+d-1}{2i+d}\prod_{i=n-d+1}^n\frac{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\n", ans);
}
posted @ 2021-04-21 16:50  mizu164  阅读(300)  评论(0编辑  收藏  举报