C-打牌的贝贝_牛客练习赛105 (nowcoder.com)
题意:
BeiBei和NingNing在玩一个卡牌游戏,共有2n张卡牌,每张牌上都有一个整数,介于1和2n之间,所有牌上的数字都是不同的。发牌阶段二人都拿到了n张牌。每个回合,游戏的过程如下:
1.若此时BeiBei没有牌了,则BeiBei判负。
2.BeiBei打出一张牌。
3.然后NingNing需要打出一张牌,使得其上的数字比BeiBei最新打出的一张牌上的数字大,如果此时NingNing无法打出这样的牌,则NingNing判负。
容易证明,该游戏总有一方会被判负。BeiBei和NingNing都足够聪明。考虑所有可能的分牌情况,使他们每个人正好分到n张牌。当BeiBei和NingNing都足够聪明时,求解出其中BeiBei、NingNing各自获胜的情况数量。
输入描述:
第一行,一个正整数T(1<T< 106),表示测试数据组数。
每组测试数据一行,包含一个整数n(1 ≤n ≤106)。
输出描述:
对于每组数据,输出一行,包含两个整数,分别表示BeiBei、NingNing获胜的情况数量,答案对109+7取模。
题解:
只要后手有n张比先手大的牌即可,类似让一个2*n的字符串有多少正则括号排列方式,
转成括号序列,先手的牌是左括号,后手的牌是右括号,只要是合法的括号序列后手就赢。因此后手的答案就是卡特兰数
这里要引入一个概念卡特兰数
#include<iostream>
using namespace std;
const int mod = 1e9+7;
long long fact[2000060],infact[2000060];
long long qpow(long long a,long long x)
{
long long ans = 1;
while(x)
{
if(x&1)
{
ans = ans*a%mod;
}
x=x/2;
a=a*a%mod;
}
return ans;
}
void init()
{
fact[0] = infact[0] = 1;
for(long long i = 1;i <= 2e6;i++)
{
fact[i] = fact[i-1]*i%mod;
infact[i] = infact[i-1]*qpow(i,mod-2)%mod;
}
}
int main()
{
init();
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t;
cin >> t;
while(t--)
{
int n;
cin >> n;
long long x = fact[2*n]*qpow(infact[n],2)%mod*qpow(n+1,mod-2)%mod;
cout<<x*n%mod<<" "<<x<<"\n";
}
}