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

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
#include
#include
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+3cout<<"0"<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));

你可能感兴趣的:(数论,BZOJ,Codevs,高精度)