BZOJ 2729 [HNOI2012]排队
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2729
题目大意: n 名男同学,m 名女同学和两名老师排队,并且任意两名女同学不能相邻,两名老师也不能相邻,求方案数。
分析:赤果果的排列组合嘛,不会就去问数学老师吧。
盗图一张:
不过还要加高精度。有一个小优化就是把因子存在一个数组里,能约掉的约掉后再高精度乘起来。但是数据很小所以没太大的必要,所以直接高精了。
附代码:
View Code
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> using namespace std; #define MaxL 2000 const long long MOD=1000000000; struct Bignum { int len; long long a[MaxL]; void init() { } Bignum() { len=0; memset(a,0,sizeof(a)); } }; int n,m; Bignum ans1,ans2; void operator *= (Bignum &p,int x) { int tmp=0; for (int i=1;i<=p.len;++i) { p.a[i]=p.a[i]*x+tmp; tmp=p.a[i]/MOD; p.a[i]%=MOD; } if (tmp) p.a[++p.len]=tmp; } Bignum operator + (Bignum x,Bignum y) { int len=max(x.len,y.len); int tmp=0; for (int i=1;i<=len;++i) { x.a[i]=x.a[i]+y.a[i]+tmp; tmp=x.a[i]/MOD; x.a[i]%=MOD; } x.len=len; if (tmp) x.a[++x.len]=tmp; return x; } Bignum operator * (Bignum x,Bignum y) { Bignum p; p.len=0; for (int i=1;i<MaxL;++i) p.a[i]=0; for (int i=1;i<=x.len;++i) { int tmp=0; for (int j=1;j<=y.len;++j) { p.a[i+j-1]=p.a[i+j-1]+x.a[i]*y.a[j]+tmp; tmp=p.a[i+j-1]/MOD; p.a[i+j-1]%=MOD; } if (tmp) p.a[i+y.len]+=tmp; } int tmp=0; for (int i=1;i<MaxL;++i) { p.a[i]=p.a[i]+tmp; tmp=p.a[i]/MOD; p.a[i]%=MOD; } for (int i=MaxL-1;i>=1;--i) if (p.a[i]) { p.len=i; break; } if (!p.len) p.len=1; return p; } void write(Bignum p) { printf("%lld",p.a[p.len]); for (int i=p.len-1;i>=1;--i) printf("%09lld",p.a[i]); printf("\n"); } Bignum A(int n,int m) { Bignum p; p.len=1; p.a[1]=1; for (int i=0;i<m;++i) p*=(n-i); return p; } int main() { scanf("%d%d",&n,&m); if (n>=1 && n+3>=m) { ans1=A(n+3,m); ans1*=((n+1)*n); } if (m>=1 && n+3>=m) { ans2=A(n+2,m-1); ans2*=(2*(n+1)*m); } write(A(n,n)*(ans1+ans2)); return 0; }
写这个题是现学的高精乘高精啊...