Description
某中学有 n 名男同学,m 名女同学和两名老师要排队参加体检。
他们排成一条直线,并且任意两名女同学不能相邻,两名老师也不能相邻,那么一共有多少种排法呢?(注意:任意两个人都是不同的)
Input
只有一行且为用空格隔开的两个非负整数 n 和 m,其含义如上所述。
对于 30%的数据 n≤100,m≤100
对于 100%的数据 n≤2000,m≤2000
Output
输出文件 output.txt 仅包含一个非负整数,表示不同的排法个数。
注意答案可能很大。
Sample Input
1 1
Sample Output
12
题解Here!
这个题比较烦人。
分类讨论一下:
- 两个老师中间只站着一个女生。
这时$\text{两老师+一女生}$应该看做一个整体。
对应答案就是:
$$A(n,n)\times A(n+1,1)\times A(2,2)\times A(n+2,m-1)$$
- 两个老师中间不止站一个女生。
这时中间一定有男生,于是随便插空就好了。
对应答案就是:
$$A(n,n)\times A(n+1,2)\times A(n+3,m)$$
然后题目中也说了,答案可能很大,所以。。。
高精度!
还是压了$5$位的高精度。。。
但是我上次不是立了个$flag$——不再写高精了吗?
嘿嘿,这次我是直接复制的高精模板哈哈哈!
不过我以后还是不写高精,只复制模板!
附代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define MAXN 10010
#define L 100000
using namespace std;
int n,m;
struct Bignum{
int len;
long long val[MAXN];
void clean(){
len=0;
memset(val,0,sizeof(val));
}
void init(int k){
clean();
len=1;
val[1]=k;
}
void write(){
printf("%lld",val[len]);
for(int i=len-1;i>=1;i--)printf("%05lld",val[i]);
printf("\n");
}
friend Bignum operator +(Bignum x,Bignum y){
Bignum s;
s.clean();
s.len=max(x.len,y.len)+12;
for(int i=1;i<=s.len;i++){
s.val[i]+=x.val[i]+y.val[i];
s.val[i+1]+=s.val[i]/L;
s.val[i]%=L;
}
for(int i=1;i<=s.len;i++){
s.val[i+1]+=s.val[i]/L;
s.val[i]%=L;
}
while(s.len&&!s.val[s.len])s.len--;
return s;
}
friend Bignum operator *(Bignum x,Bignum y){
Bignum s;
s.clean();
s.len=x.len+y.len+12;
for(int i=1;i<=x.len;i++)
for(int j=1;j<=y.len;j++){
s.val[i+j-1]+=x.val[i]*y.val[j];
s.val[i+j]+=s.val[i+j-1]/L;
s.val[i+j-1]%=L;
}
for(int i=1;i<=s.len;i++){
s.val[i+1]+=s.val[i]/L;
s.val[i]%=L;
}
while(s.len&&!s.val[s.len])s.len--;
return s;
}
}ans;
inline int read(){
int date=0,w=1;char c=0;
while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
return date*w;
}
Bignum A(int n,int m){
Bignum s,x;
s.clean();
if(m>n)return s;
s.init(1);
if(!m)return s;
for(int i=n-m+1;i<=n;i++){
x.clean();x.init(i);
s=s*x;
}
return s;
}
inline void solve(int n,int m){
ans=A(n,n)*A(n+1,2)*A(n+3,m)+A(n,n)*A(n+1,1)*A(2,2)*A(m,1)*A(n+2,m-1);
ans.write();
}
int main(){
n=read();m=read();
solve(n,m);
return 0;
}