CF1739 C. Card Game

题目链接

题意简述

有这样一个游戏 , 有一摞编号为 \(1\sim n\) 的卡片( 保证 \(n\) 为偶数),编号大的卡片比编号小的卡片更"强".
两名玩家玩这个游戏,他们平均分这 \(n\) 张卡片 ,即每个人有 \(n \over 2\)张卡片.这也就意味着一张牌只可能属于一个玩家.
每一个玩家的回合: 第一个玩家先出牌,然后下一个玩家出一张更强的牌. 如果一个玩家出牌后对手没有更大的牌,那么这个玩家就赢了. 一个玩家的回合结束后,轮到另一个玩家的回合. 如果某个回合结束后两个玩家都没有牌了,那么游戏平局.

给你牌的个数 \(n\) ,请分别计算出 玩家 \(A\) 赢, 玩家 \(B\) 赢,平局 的牌的分配方法数

样例

点击查看样例

分析

解法有很多,官方题解是 \(DP\) 或 组合数学(详见 \(Tutorial\) )

下面给出另一种解法(其实是没看懂官方题解)

注意,在一个玩家的回合结束后,另一个玩家的回合开始,这意味着: A打出牌后,B跟着打出,然后B再打出牌,A再跟着打出.

考虑 \(n\) 张牌的情境.
\(n=2\) 时, 只有两种情况,要么 \(A\) 赢,要么平局.
当 $n > 2\ $时
如果 \(A\)\(n\) 号牌, 那么 \(A\) 一定获胜. 此时 \(A\) 赢的牌的分配方案有 \(C^{n\over 2}_{n-1}\)
下面只考虑 \(B\)\(n\) 号牌的情况

\[tips:事实上,\ A\ 必须首先打出一张比\ B\ 的手牌里除\ n\ 以外的牌都大的牌,把\ B\ 的\ n\ 号牌逼出来,否则:如果给\ B\ 机会先打了一张小牌,然后\ B\ 把\ n\ 打出来,那么\ A\ 就输了. \]

如果 \(B\)\(n\) 号牌
  如果 \(B\)\(n-1\) 号牌,那么无论 \(A\) 打出任何牌 , \(B\)\(n\) 号牌响应,然后\(B\)打出 \(n-1\) 号牌即可获胜.
  如果 \(A\)\(n-1\) 号牌,
    如果 \(B\)\(n-2\) 号牌 ,那么 \(B\) 赢了,因为①如果 \(A\) 打出 \(n-1\) 号牌时, \(B\) 使用 \(n\) 号牌,然后打出 \(n-2\) 号牌,然后 \(B\) ,获胜.②如果 \(A\) 打出其他牌, \(B\) 使用 \(n-2\) 号牌,然后打出 \(n\) 号牌即可获胜.
    如果 \(A\)\(n-2\) 号牌
      如果 \(B\)\(n-3\) 号牌 : \(A\) 先出 \(n-2\) 号牌把 \(B\)\(n\) 号牌逼出,然后 \(B\)\(n-3\) 号牌, \(A\)\(n-1\) 号牌响应 .然后再轮到 \(A\) 出牌,注意,由于\(n-3 \sim n\) 的牌都用掉了,此时相当于从 \(n-4\) 的牌堆中出牌.如果此时没有牌了,则平局
      如果 \(A\)\(n-3\) 号牌, \(B\) 无论怎么拿都输了 , \(A\) 先逼出 \(B\)\(n\) 号牌 ,然后 \(B\) 剩下的牌比 \(A\)所有牌都小. \(B\) 无论出哪张, \(A\) 都能响应,然后 \(A\) 再出一张牌 , \(B\) 就无法响应了, \(B\) 输. 这为 \(A\) 提供了 \(C^{{n\over 2} -1}_{n-4}\) 种方案

综上所述:
当 $n \geq 4 $时. \(A\) 赢的情况有 \(f(n) = C^{n\over 2}_{n-1}+C^{{n\over 2} -1}_{n-4} +f(n-4)\)
平局的情况只有 \(1\) 种 , \(B\) 赢的情况有 $C^{n\over 2} _n - 1 - f(n) $
\(n < 4\)时,显然 \(n\) 只能取 \(2\),那么 \(A\) 赢的方案只有给 \(A\) \(2\) 号牌,给 \(B\) \(1\) 号牌.平局的话就是把 \(2\)号牌给 \(B\) . 也即 \(f(2) = 1\)

代码

点击查看代码
#include<stdio.h>
#include<iostream>
using namespace std;
typedef long long LL;
int mod =998244353;
int n=10;
const int N = 70;
long long int c[N][N];//记录组合数.
long long int f[N];

int choose()
{
	//从大佬那学来的求组合数的方法.
	for(int i=0;i<=n;i++)
	{
		for(int j=0;j<=i;j++)
		{
			if(j==0)c[i][j]=1; 
			else c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
		}	
	}
	f[2]=1;
	for(int i=4;i<=n;i+=2)
	{
		f[i]=c[i-1][i/2]+c[i-4][i/2-1]+f[i-4];
		f[i]%=mod;
	}
	printf("%lld %lld %lld\n",f[n],(c[n][n/2]-f[n]-1+mod)%mod,1LL);
	return 0;
}
int main()
{
	//freopen("uva.txt","r",stdin);
	
	int T;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		choose();
	}
	
	return 0;
}

posted @ 2022-10-05 16:23  LZH_03  阅读(30)  评论(0编辑  收藏  举报