BZOJ2729 [HNOI2012]排队
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!
题目链接:BZOJ2729
正解:组合数学
解题报告:
考虑直接用组合数算。
我先把男生全排列,就会有$n+1$个空位,留给老师来站。
之后有$n+3$个空位,给女生来站。
所以方案数就是${n!*P_{n+1}^{2}*P_{n+3}^{m}}$,P表示排列的方案数
然后就会愉快地发现过不了样例,像我就SB地想了20分钟没想通为啥答案小了...
考虑我插入女生的时候可能会把原本相邻的两个老师隔开,所以我需要另外考虑。
只考虑老师相邻的情况,再强制把一个女生放在他们中间,其余的全排列即可,方案数就是:
${n!*(n+1)*2*P_{n+2}^{m-1}*m}$$=$${(n+1)!*2*P_{n+2}^{m-1}*m}$
把上面两个方案数加起来就可以了,这道题需要写高精度...
//It is made by ljh2000 #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <ctime> #include <vector> #include <queue> #include <map> #include <set> #include <string> #include <complex> using namespace std; typedef long long LL; typedef long double LB; typedef complex<double> C; const double pi = acos(-1); const int MAXN = 100011; const int mod = 100000000; //n!*(n+1)*[(n+2)! / (n+3-m)!] * [(n+3)*n+2*m] int n,m; inline int getint(){ int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w; } struct num{ LL a[MAXN]; int len; inline void print(){ printf("%lld",a[len]); for(int i=len-1;i>=1;i--) printf("%08lld",a[i]); } }a; inline void cheng(int x){ for(int i=1;i<=a.len;i++) a.a[i]*=x; for(int i=1;i<=a.len;i++) a.a[i+1]+=a.a[i]/mod,a.a[i]%=mod; while(a.a[a.len+1]>0) a.len++,a.a[a.len+1]+=a.a[a.len]/mod,a.a[a.len]%=mod; } inline void work(){ n=getint(); m=getint(); a.len=1; a.a[1]=1; for(int i=2;i<=n;i++) cheng(i); cheng(n+1); cheng((n+3)*n+2*m); for(int i=n+4-m;i<=n+2;i++) cheng(i); a.print(); } int main() { work(); return 0; }
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!