排排坐看电影

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;
}

上一篇下一篇

猜你喜欢

热点阅读