[JZOJ 2804]【HNOI2012】排队(queue)

Description
某中学有n名男同学,m名女同学和两名老师要排队参加体检。他们排成一条直线,并且
任意两名女同学不能相邻,两名老师也不能相邻,那么一共有多少种排法呢?(注意任意两个人都是不同的)
Input
输入只有一行且为用空格隔开的两个非负整数n和m,其含义如上所述。
Output
仅包含一个非负整数,表示不同的排法个数.
Sample Input
【输入样例 1】
1 1
【输入样例 2】
7 3
Sample Output
【输出样例 1】
12
【输出样例 2】
220631040
Data Constraint
Hint
对于30%, n<=100,m<=100
对于100%, n<=2000,m<=2000

The Solution

这道题目,我们可以先分类讨论。
如果 n+3<m 则显然无解,输出0,
如果 n+3>=m 则进行分析:

我们可以先处理男生和老师。

① 排男生。因为一共有 n 个男生,所以有 n! 种排法。
② 排老师。
这个时候,就有两种情况了。

第一种,我们把两个老师在这一步就分开放。
将 2 个老师插入到已经排好的男生中。
因为有 n 个男生,所以一共有 n+1 个位置可以插入老师,排列的方法有

A2n+1

第二种,我们把两个老师排在一起。

把两个老师看成一个老师,这个新的老师有两种情况(因为两个老师可以顺序不同),然后再把这个新的老师插入到男生当中,排列的方法有 2(n+1) 种。

③排女同学。

对于老师的第一种排法,我们已经不需要考虑老师和男同学的区别了,因为老师的限制条件已经被解决了。
所以,我们要将 m 个女生插入 n+1+2=n+3 个空位中互相隔开,

Amn+3
种排法,

对于老师的第二种排法,
我们需要将一个女生插入到两个老师之中(即:(老师,女生,老师),然后跟第一种情况一样的处理,

mAm1n+2
种排法。

综上所述,
一共有:

n!Amn+3A2n+1mAm1n+22(n+1)

提取公因式得:

(n(n+3)+m2)n!Am2n+2

最后高精度即可,可以压位。

PS.排列的计算为:
这里写图片描述
这里写图片描述

CODE

#include <cstdio>
#include <iostream>
#include <cstring>
#define fo(i,a,b) for (int i=a;i<=b;i++)
#define fd(i,a,b) for (int i=a;i>=b;i--)
#define N 2005
#define ya 100000000
using namespace std;
struct note
{
    int len;
    long long num[N];
}a;
int n,m;
note gjc(note a,int x)
{
    note c;
    memset(c.num,0,sizeof(c.num));
    c.len=a.len;
    fo(i,1,c.len)
    {
        c.num[i]+=a.num[i]*x;
        c.num[i+1]+=c.num[i]/ya;
        c.num[i]=c.num[i]%ya;
    }
    while (c.num[c.len+1]) c.len++;
    return c;
}
int main()
{
    scanf("%d%d",&n,&m);
    if (n+3<m) {printf("0\n"); return 0;}
    int k=n*(n+3)+m*2;
    a.len=1;
    a.num[1]=k;
    fo(i,1,n+1) a=gjc(a,i);
    fo(i,n-m+4,n+2) a=gjc(a,i);
    printf("%d",a.num[a.len]);
    fd(i,a.len-1,1) printf("%08d",a.num[i]);
    return 0; 
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值