AT_agc053_c [AGC053C] Random Card Game 题解

首先容易发现含有 \(2n\) 的那一堆不会被删掉,记其为 \(a\),另一堆为 \(b\)。记 \(p_i\) 表示最小的 \(j\) 满足 \(j\ge i\land a_j>b_i\),那么至少要在 \(a\) 堆中删除 \(\max\{p_i-i,0\}\) 个数才能删除 \(b_i\),那么答案就是 \(n+\max\{p_i-i\}\)

\(f(x)\) 表示操作次数 \(\le x+n\) 的概率,那么期望操作次数就是 \(2n-\sum_{i=0}^{n-1}f(i)\),容易得到:

\[f(x)=\prod_{i=1}^n \left(1-\frac{1}{i+\min\{i+x,n\}}\right) \]

分奇偶处理前/后缀逆元积即可,时间复杂度 \(\mathcal O(n+\log B)\)

参考代码:

#include<bits/stdc++.h>
#define ll long long
#define mxn 2000003
#define md 1000000007
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define rept(i,a,b) for(int i=(a);i<(b);++i)
#define drep(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
int n;
ll ans,inv[mxn],d[mxn],d1[mxn],d2[mxn],d3[mxn],d4[mxn];
ll power(ll x,int y){
	ll ans=1;
	for(;y;y>>=1){
		if(y&1)ans=ans*x%md;
		x=x*x%md;
	}
	return ans;
}
ll solve(int k){
	ll ans=d[n*2-k+1];
	if(k&1)ans=ans*d1[n*2-k]%md*d3[k+1]%md;
	else ans=ans*d2[n*2-k]%md*d4[k+1]%md;
	return ans;
}
signed main(){
	cin>>n,ans=n;
	inv[1]=1;
	rep(i,2,n<<1)inv[i]=inv[md%i]*(md-md/i)%md;
	d[(n<<1)+1]=1;
	drep(i,(n<<1),1)d[i]=d[i+1]*(1-inv[i])%md;
	d1[1]=1;
	rep(i,2,(n<<1)){
		if(i&1)d1[i]=d1[i-1]*(1-inv[i])%md;
		else d1[i]=d1[i-1];
	}
	d3[n<<1]=power(d1[n<<1],md-2);
	drep(i,n<<1,2){
		if(i&1)d3[i-1]=d3[i]*(1-inv[i])%md;
		else d3[i-1]=d3[i];
	}
	d2[1]=1;
	rep(i,2,(n<<1)){
		if(!(i&1))d2[i]=d2[i-1]*(1-inv[i])%md;
		else d2[i]=d2[i-1];
	}
	d4[n<<1]=power(d2[n<<1],md-2);
	drep(i,n<<1,1){
		if(!(i&1))d4[i-1]=d4[i]*(1-inv[i])%md;
		else d4[i-1]=d4[i];
	}
	rept(i,0,n)ans=(ans-solve(i))%md;
	cout<<(ans*2%md+md)%md;
	return 0;
}
posted @ 2024-12-19 08:04  zifanwang  阅读(5)  评论(0编辑  收藏  举报