bzoj2729: [HNOI2012]排队
高精度+排列组合。
如果计算老师能挨在一起的情况 有 (n+2)! * A(n+3,m)
老师一定挨宰一起的情况 有 2*(n+1)!*A(n+2,m)。
相减就是答案。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 3000; const int mod = 10000; struct bigint { int a[maxn+10]; int& operator[] (int x) { return a[x]; } bigint operator * (int x) { bigint c; for(int i=1;i<=maxn;i++) { c[i]+=a[i]*x; c[i+1]+=c[i]/mod; c[i]=c[i]%mod; } return c; } bigint operator - (bigint b) { bigint c; for(int i=1;i<=maxn;i++) { c[i]+=a[i]-b[i]; if(c[i]<0) {c[i]+=mod; c[i+1]--;} } return c; } void print() { int k; for(k=maxn;k>=1;k--) if(a[k]) break; printf("%d",a[k]); for(int i=k-1;i>=1;i--) printf("%04d",a[i]); printf("\n"); } bigint() { memset(a,0,sizeof(a)); } }t1,t2; int n,m; int main() { scanf("%d%d",&n,&m); t1[1]=1; t2[1]=2; for(int i=1;i<=n+2;i++) t1=t1*i; for(int i=n+4-m;i<=n+3;i++) t1=t1*i; for(int i=1;i<=n+1;i++) t2=t2*i; for(int i=n+3-m;i<=n+2;i++) t2=t2*i; t1=t1-t2; t1.print(); return 0; }