题目大意:一开始有n张牌,每个牌上面写了一个数字,数字的范围是1~n,并且每个牌上的数字都不一样,有两个人A和B,他们平均的把这n张牌分成两份,分别给与A和B。现在规定一个游戏。
游戏由A开始进行:首先A拿一张牌出来,B也拿一张比A拿的牌大的牌,如果B拿不出,B就输了;
然后把A,B两人拿出来的牌丢入牌堆。之后轮到B拿一张牌,之后A拿一张比B的牌大的数,如果A拿不出A就输了,如此反复,直到有人输或者全部拿完并且没有人赢,那么就是平局。
给你一个n代表牌的数量
问你让A赢的拿法和A输的拿法和平局的拿法。
思路:拿牌的问题可以理解成一个组合数的问题,可以建议一个c数组把60以内的组合全部算出来并且取余mod,然后我们讨论
A赢的可能:
1 )拿一张最大的牌,因为只要A出了这张牌B一定没有比这张牌大的牌 就是c[n-1][n/2-1],从n-1张排中选出(n/2)-1张牌的可能性
2 )如果第一句是平局,如果A还有可能赢的话那么 一开始A 一定有第二大的牌并且B有第一大的牌 赢的可能剩下就是去掉剩下的两张牌之后的选法 c[i-2][i/2-1]减去B赢的可能 win[i-2]再减去平局的可能1,最后加起来取余再和1 的可能相加就得到答案了。
/**
* ┏┓ ┏┓+ +
* ┏┛┻━━━┛┻┓ + +
* ┃ ┃
* ┃ ━ ┃ ++ + + +
* ████━████+
* ◥██◤ ◥██◤ +
* ┃ ┻ ┃
* ┃ ┃ + +
* ┗━┓ ┏━┛
* ┃ ┃ + + + +Code is far away from
* ┃ ┃ + bug with the animal protecting
* ┃ ┗━━━┓ 神兽保佑,代码无bug
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛ + + + +
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛+ + + +
*/
#include<cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include<vector>
#include<queue>
#include<map>
#define ll long long
using namespace std;
const int N=1000000+100,mod= 998244353,maxn=70;
ll n ,m,h;
ll win[N],lose[N];
ll c[maxn][maxn];
void init ()
{
for (int i = 0; i < maxn; i++)
for (int j = 0; j <= i; j++)
if (!j)
c[i][j] = 1;
else
c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mod; //预处理出来从i个里面跳出来j个的组合数
for(int i =4;i<=60;i+=2)
{
win[i]=(c[i-1][i/2-1]+( c[i-2][i/2-1] - win[i-2] -1+mod)%mod)%mod;
lose[i]=(c[i][i/2]-win[i]-1+mod)%mod;
}
}
int main()
{
int t;
cin>>t;
win[2]=1,lose[2]=0;
init();
while(t--)
{
cin>>n;//总次数为Cn n/2 ,平局为1,赢只要有n,c(n-1) (n/2-1) +第二大和第三大绑定的次数(c(n-4) (n/2)-3)*2-1 ,输为
cout<<win[n]<<" "<<lose[n]<<" "<<1<<endl;
}
return 0;
}