BZOJ 2729: [HNOI2012]排队 排列组合 + 高精度
Description
某中学有 n 名男同学,m 名女同学和两名老师要排队参加体检。他们排成一条直线,并且任意两名女同学不能相邻,两名老师也不能相邻,那么一共有多少种排法呢?(注意:任意两个人都是不同的)
Input
只有一行且为用空格隔开的两个非负整数 n 和 m,其含义如上所述。
对于 30%的数据 n≤100,m≤100
对于 100%的数据 n≤2000,m≤2000
Output
输出文件 output.txt 仅包含一个非负整数,表示不同的排法个数。注意答案可能很大。
题解:不难的一道组合题
分类讨论一下:
(1) 老师由男生隔开
$A(n,n)\times A(n+1,2)\times A(n+3,m)$
(2) 老师由女生隔开
将两个老师中间夹一个女生视为一个整体
$A(n,n)\times A(n+1,1)\times A(n+2,m-1)$
最后累加一下即可
(1) 老师由男生隔开
$A(n,n)\times A(n+1,2)\times A(n+3,m)$
(2) 老师由女生隔开
将两个老师中间夹一个女生视为一个整体
$A(n,n)\times A(n+1,1)\times A(n+2,m-1)$
最后累加一下即可
#include<bits/stdc++.h> #define maxn 10003 #define ll long long #define p 10000000000ll using namespace std; ll base[maxn]; int n,m,len=1; void multiply(int x) { ll pre=0,tmp; for(int i=1;i<=len;i++) { tmp=base[i]*x; base[i]=tmp%p+pre; pre=tmp/p; } if(pre)++len, base[len]=pre; } int main(){ scanf("%d%d",&n,&m); base[1]=1; for(int i=1;i<=n;i++)multiply(i); for(int i=n-m+4;i<=n+2;i++)multiply(i); multiply(n+1); multiply(n*(n+3)+2*m); printf("%lld",base[len]); while(--len)printf("%010lld",base[len]); return 0; }