AGC 053 C Random Card Game 题解

AGC 053 C Random Card Game 题解

容易发现最终被消除的牌堆一定是不包含\(2n\)的。

设不包含\(2n\)的牌堆为B,包含\(2n\)的牌堆为\(A\)。

最优策略如下:

  1. 若存在一个\(k\)满足\(B_k<A_k\),则进行操作\(k\)。
  2. 否则进行操作\(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;
}
上一篇:如何测试重签名的应用功能是否正常


下一篇:如何解决Eclipse集成华为AGC SDK工具包运行失败问题