AGC 053 C Random Card Game 题解
容易发现最终被消除的牌堆一定是不包含\(2n\)的。
设不包含\(2n\)的牌堆为B,包含\(2n\)的牌堆为\(A\)。
最优策略如下:
- 若存在一个\(k\)满足\(B_k<A_k\),则进行操作\(k\)。
- 否则进行操作\(1\)。
容易发现答案是\(\max(0,\max\{d_i-i\})+n\),\(d_i\)是最小的满足\(A_j>B_i\)的\(j\)。
所以可以枚举答案\(\leq k\),也就是\(\exists_{j\in [1,i+k]} A_j>B_i\)。
贡献为:
\[i!\cdot (i+1)\cdot (i+1)\cdot (i+3)\cdot (i+3)...(2n-i-1)\cdot (2n-i-1)\cdot [(2n-i)\cdot...\cdot(n-1)] \]可以预处理之后\(O(1)\)计算。
code:
/*
{
######################
# Author #
# Gary #
# 2021 #
######################
*/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
//inline int read(){
// int x=0;
// char ch=getchar();
// while(ch<'0'||ch>'9'){
// ch=getchar();
// }
// while(ch>='0'&&ch<='9'){
// x=(x<<1)+(x<<3)+(ch^48);
// ch=getchar();
// }
// return x;
//}
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
const int MOD=1e9+7;
const int MAXN=2e6+233;
int fact[MAXN],calc[MAXN],ifact[MAXN],fact2[MAXN],ifact2[MAXN];
int quick(int A,int B){
if(B==0) return 1;
int tmp=quick(A,B>>1);
tmp=1ll*tmp*tmp%MOD;
if(B&1) tmp=1ll*tmp*A%MOD;
return tmp;
}
int inv(int A){return quick(A,MOD-2);}
int main(){
fill(fact,fact+MAXN,1);
fill(ifact,ifact+MAXN,1);
fill(fact2,fact2+MAXN,1);
fill(ifact2,ifact2+MAXN,1);
rb(i,1,2000000){
fact[i]=1ll*fact[i-1]*i%MOD;
if(i>=2)
fact2[i]=1ll*fact2[i-2]*i%MOD;
else
fact2[i]=i;
}
ifact[2000000]=inv(fact[2000000]);
ifact[2000000-1]=inv(fact[2000000-1]);
ifact2[2000000-1]=inv(fact2[2000000-1]);
ifact2[2000000]=inv(fact2[2000000]);
rl(i,2000000-2,1){
ifact[i]=1ll*ifact[i+1]*(i+1)%MOD;
ifact2[i]=1ll*ifact2[i+2]*(i+2)%MOD;
}
int n;
scanf("%d",&n);
rb(i,0,n-1){
calc[i]=fact[i];
calc[i]=1ll*calc[i]*fact2[2*n-i-1]%MOD*ifact2[max(0,i-1)]%MOD;
calc[i]=1ll*calc[i]*fact2[2*n-i-1]%MOD*ifact2[max(0,i-1)]%MOD;
calc[i]=1ll*calc[i]*fact[2*n-1]%MOD*ifact[2*n-i-1]%MOD;
}
int rest=0;
rb(i,1,n-1){
(rest+=1ll*i*(MOD+calc[i]-calc[i-1])%MOD)%=MOD;
}
rest=1ll*rest*ifact[2*n]%MOD;
rest=2ll*rest%MOD;
(rest+=n)%=MOD;
cout<<rest<<endl;
return 0;
}