[HNOI 2012]排队

来源:互联网 发布:虚拟机安装mac 编辑:程序博客网 时间:2024/05/21 09:48

这道题是湖南省选的一道题,与其说是考算法,不如说是考数学,这是一道较为“纯”的数学题。

首先来看一下题目:


某中学有n 名男同学,m 名女同学和两名老师要排队参加体检。他们排成一条直线,并且任意两名女同学不能相邻,两名老师也不能相邻,那么一共有多少种排法呢?(注意:任意两个人都是不同的)

对于30%的数据n≤100,m≤100

对于100%的数据n≤2000,m≤2000


【分析】:

这一道题主要分两种情况讨论

1、当 n+3<m 时,显然无解,易证。

2、当 n+3>=m 时,显然又可以分两种情况进行讨论:

(1).假定老师中间没有男生,这中间必然有且只有一个女生,这时将这三个人(TGT)看成一个男生,全排列即可,此时女生“插板”即可。

(2).如果老师中间有男生,则用男生和老师的全排列减去老师相邻的情况,再对女生插板可解。

具体公式自己推吧,上代码:

(由于此题只会涉及到单精度,于是long long压15位)

#include <iostream>#include <cstdio>#include <cstdlib>#define mod 1000000000 //todo:clac (n^2+3n+2m)*{Πi(i∈[1,n+1])}*{Πj(j∈[n+4-m,n+2])} using namespace std;long long a[2000];int n,m;inline void init(){cin>>n>>m;if(n+3<m){cout<<0;exit(0);}a[0]=1;a[1]=n*n+3*n+2*m;}inline void mul(const int &x){for(int i=1;i<=a[0];i++)a[i]*=x;for(int i=1;i<=a[0];i++)a[i+1]+=a[i]/mod,a[i]%=mod;while(a[a[0]+1]) a[0]++;}inline void work(){for(int i=1;i<=(n+1);i++)mul(i);for(int j=n+4-m;j<=(n+2);j++)mul(j);}inline void print(){cout<<a[a[0]];for(int i=a[0]-1;i>0;i--)printf("%09d",a[i]);}int main(){freopen("in","r",stdin);freopen("out","w",stdout); init();work();print();return 0;} 

0 0
原创粉丝点击