看到n<=20我就想暴力打表找出所有情况了;但死在第15组,要花的时间太久了;
然后就想着推嘛;每次加入一个当前情况最大的数;合理的位置就是高低高低高;所以要找前面高低的情况n,后面低高的情况m;那总情况就是n*m;
所以就是求n,m还有选择前面数的方法数C【i-1】【j】一共i个数,将i放在j位置上
组合数可以打表,n,m就递推来求;
dp【i】【0】表示i个数高低的情况;dp【i】【1】表示i个数低高的情况;
写下n=3,n=4;的情况就能推断出dp【i】【0】=dp【i】【1】=总情况数/2;
注意1特判;
#include<bits/stdc++.h>
using namespace std;
long long dp[25][2],ans[25];
long long c[20][25],t;
void init()
{
c[1][1]=1;
c[1][0]=1;
for(int i=2;i<=20;i++)//算组合数
{
c[i][0]=c[i][i]=1;
for(int j=1;j<i;j++)
c[i][j]=c[i-1][j]+c[i-1][j-1];
}
dp[1][0]=dp[1][1]=dp[0][0]=dp[0][1]=1;//初始为1
for(int i=2;i<=20;i++)
{
t=0;//t记录总方法数
for(int j=0;j<i;j++)
{
t+=dp[j][0]*dp[i-j-1][1]*c[i-1][j];
}
dp[i][0]=dp[i][1]=t/2;
}
}
int main()
{
init();
int cas;
scanf("%d",&cas);
while(cas--)
{
int cs,n;
scanf("%d%d",&cs,&n);
if(n==1)
{
printf("%d 1\n",cs);
continue;
}
printf("%d %I64d\n",cs,dp[n][0]<<1);
}
return 0;
}