2023牛客暑期多校3 B Auspiciousness

题意

Dog Card is a card game. In the game, there are a total of \(2n\) cards in the deck, each card has a value, and the values of these \(2n\) cards form a permutation of \(1\sim 2n\). There is a skill that works as follows:

  1. Draw a card from the top of the deck.

  2. If the deck is empty, then skip to step 3, otherwise you guess whether the card on the top of the deck has a higher value than your last drawn card and draw a card from the top of the deck. If your guess is correct, then repeat this step, otherwise skip to step 3.

  3. End this process.

Nana enjoys playing this game, although she may not be skilled at it. Therefore, her guessing strategy when using this skill is simple: if the value of the last drawn card is less than or equal to \(n\), then she guesses that the next card's value is higher; otherwise, she guesses that the next card's value is lower. She wants to know, for all different decks of cards (Obviously, there are \((2n)!\) cases), how many cards she can draw in total if she uses the skill only once in each case. Since this number can be very large, please provide the answer modulo a given value.

\(n\leq 300\)

题解

能一直抽下去的情况无非就是\(\leq n\)的上升段和\(> n\)的下降段交替出现。

直接枚举不太可行,所以需要用到DP。

\(f(i, j, 0/1)\)表示\(\leq n\)的用了\(i\)张,\(> n\)的用了\(j\)张,最后一段是上升/下降段的方案数。

注意猜测失败时会多抽一张,需要特殊考虑。方法是统计答案时的最后一段多取一个数。

时间复杂度\(O(n^3)\)

constexpr int N=310;
int mod;
int binom[N][N], fac[2*N];

void init(int n){
	for(int i=0; i<=n; ++i){
		binom[i][0]=binom[i][i]=1;
		for(int j=1; j<i; ++j)
			binom[i][j]=(binom[i-1][j-1]+binom[i-1][j])%mod;
	}
	fac[0]=1;
	for(int i=1; i<=2*n; ++i)
		fac[i]=(int64)fac[i-1]*i%mod;
}

int f[N][N][2];

void realMain(){
	int n=read<int>(); read(mod);
	init(n);
	int ans=0;
	for(int i=0; i<=n; ++i)
		for(int j=0; j<=n; ++j)
			f[i][j][0]=f[i][j][1]=0;
	f[0][0][0]=f[0][0][1]=1;
	for(int s=0; s<=2*n; ++s)
		for(int i=0; i<=n && i<=s; ++i){
			int j=s-i;
			if(j>n) continue;
			for(int k=1; k<=n-i; ++k){ // f[i][j][1] -> f[i+k][j][0]
				f[i+k][j][0]=(f[i+k][j][0]+(int64)f[i][j][1]*binom[n-i][k]%mod)%mod;
				ans=(ans+(int64)f[i][j][1]*binom[n-i][k]%mod*(k-1)%mod*fac[2*n-i-j-k]%mod*(i+j+k)%mod)%mod;
			}
			for(int k=1; k<=n-j; ++k){ // f[i][j][0] -> f[i][j+k][1]
				f[i][j+k][1]=(f[i][j+k][1]+(int64)f[i][j][0]*binom[n-j][k]%mod)%mod;
				ans=(ans+(int64)f[i][j][0]*binom[n-j][k]%mod*(k-1)%mod*fac[2*n-i-j-k]%mod*(i+j+k)%mod)%mod;
			}
		}
	ans=(ans+(int64)(f[n][n][0]+f[n][n][1])%mod*(2*n)%mod)%mod;
	printf("%d\n", ans);
}
int main(){
	for(int t=read<int>(); t--; ) realMain();
	return 0;
}

posted on 2023-07-24 15:17  autoint  阅读(93)  评论(3编辑  收藏  举报

导航