BZOJ_P2729[HNOI2012]排队&Codevs_P1994 排队(数论)

84 篇文章 0 订阅
54 篇文章 0 订阅

Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 1362 Solved: 632
[Submit][Status][Discuss]
Description

某中学有 n 名男同学,m 名女同学和两名老师要排队参加体检。他们排成一条直线,并且任意两名女同学不能相邻,两名老师也不能相邻,那么一共有多少种排法呢?(注意:任意两个人都是不同的)

Input
只有一行且为用空格隔开的两个非负整数 n 和 m,其含义如上所述。
对于 30%的数据 n≤100,m≤100
对于 100%的数据 n≤2000,m≤2000

Output
输出文件 output.txt 仅包含一个非负整数,表示不同的排法个数。注意答案可能很大。

Sample Input
1 1

Sample Output
12

HINT
Source
day1

排列组合
公式:

A(n,n)(A(n+1,2)*A(n+3,m)+A(2,2)(n+1)*A(n+2,m-1)*m)

1.考虑男生顺序 n!
2.考虑将老师和女生分别加入队中,老师A(n+1,2),女生A(n+3,m);
3.考虑两个老师之间有女生 老师排列A(2,2),(n+1)(老师,女生,老师),剩余女生排列A(n+2,m-1),插入老师之间的女生 m
综上所述A(n,n)* (A(n+1,2) A(n+3,m)+A(2,2)(n+1)* A(n+2,m-1)*m)
提取公因式(n* (n+3)+m* 2)* A(n,n)*A(n+2,m-2)

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define N 10005
#define Mod 100000000
struct Big{
    int l;
    long long num[N];
}a;
int n,m;
void mul(const int &x){
    for(int i=1;i<=a.l;i++)
        a.num[i]*=x;
    for(int i=1;i<=a.l;i++)
        if(a.num[i]>9) a.num[i+1]+=a.num[i]/Mod,a.num[i]%=Mod;
    while(a.num[a.l+1]) a.l++;
}
void print(){
    printf("%d",a.num[a.l]);
    for(int i=a.l-1;i>=1;i--) printf("%08d",a.num[i]);
    putchar('\n');
}
void work(){
    int mid=n*(n+3)+m*2,l;
    a.l=1;a.num[1]=mid;
    for(int i=1;i<=n+1;i++) mul(i);
    for(int i=n-m+4;i<=n+2;i++) mul(i);
    print();
}
int main(){  
    scanf("%d%d",&n,&m);
    if(n+3<m) cout<<"0"<<endl;
    else work();
    return 0;
}  
//  else print(A(n,n)*(A(n+1,2)*A(n+3,m)+A(2,2)*(n+1)*A(n+2,m-1)*m));
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值