排排坐看电影
2018-06-16 本文已影响0人
见习炼丹师
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <utility>
#include <vector>
#define inf 0x3f3f3f3f
#define true 1 //用来标记男生和女生的常量
#define false 0
using namespace std;
int B(int N) //计算n的阶乘
{
int answer = 1;
for (int i = 1; i <= N; i++)
answer *= i;
return answer;
}
long long Count(long long n, long long m, int q, int qq)
{
if (n > 0 && m > 0) //如果男生和女生都大于0
{
if (q== true) //如果当前位置的前一个人是男生,则该位置放男生或女生都可以
return m * Count(n, m - 1, false, q) + n * Count(n - 1, m, true, q);
else //如果前一个位置是女生
{
if (qq == true) //且再前一个是男生,则该位置也是可以既放男生,或放女生
return n * Count(n - 1, m, true, q)+ m * Count(n, m - 1, false, q);
else //再前一个也是女生,或者前面只有一个女生,(再前一个没有人也就是qq==-1)则该位置一定要放男生;
return n * Count(n - 1, m, true, q) ;
}
}
else if (n > 0) //如果女生没了,那剩下的n个男生可以形成n!种放法。
{
return B(n);
}
else if (m > 0) //如果在考虑当前位置的时候已经是只剩女生了
{
if (q == true) //如果前一个位置为男生则在该位置放女生
return m * Count(n, m - 1, false, q);
else //如果前一个位置为女生则接下来的放置肯定是不符合题目要求的
return 0;
}
else if (!n && !m) //所有人都放置完毕
return 1;
}
int main()
{
//freopen("input.txt","r",stdin);
int w;
long long n, m;
long long a;
scanf("%d", &w);
while (w--)
{
scanf("%lld%lld", &n, &m);
if (m > (n << 1) || !n) //如果 m>2n 或者n=0,就直接输出0
{
printf("0\n");
continue;
}
a = n * Count(n - 1, m, true, -1) + m * Count(n, m - 1, false, -1);
printf("%lld\n", a);
}
return 0;
}