题目描述:
某中学有 n 名男同学,m 名女同学和两名老师要排队参加体检。
他们排成一条直线,并且任意两名女同学不能相邻,两名老师也不能相邻,那么一共有多少种排法呢?(注意:任意两个人都是不同的)
输入格式:
只有一行且为用空格隔开的两个非负整数 n 和 m,其含义如上所述。
输出格式:
仅包含一个非负整数,表示不同的排法个数。注意答案可能很大。
数据范围 0≤n,m≤2000
输入样例:
1 1
输出样例:
12
题目链接:排队
分析:本题考数学的排列组合,结果非常大,long的数据范围都不够,可以直接用BigInteger来处理大数
思路:
- 把两个老师当作男生看待,然后去在他们之间(n+3个空位)插入女生。总方案为: A ( n + 2 , n + 2 ) ∗ A ( m , m ) ∗ C ( n + 3 , m ) A(n+2,n+2) * A(m,m) * C(n+3,m) A(n+2,n+2)∗A(m,m)∗C(n+3,m)
- 两个老师排在一起的情况方案为(把两个老师看成一个男生):
A ( 2 , 2 ) ∗ A ( n + 1 , n + 1 ) ∗ A ( m , m ) ∗ C ( n + 2 , m ) A(2,2) * A(n+1,n+1) * A(m,m) * C(n+2,m) A(2,2)∗A(n+1,n+1)∗A(m,m)∗C(n+2,m) - 用总方案减去两个老师排在一起的情况:
A ( n + 2 , n + 2 ) ∗ A ( m , m ) ∗ C ( n + 3 , m ) − A ( 2 , 2 ) ∗ A ( n + 1 , n + 1 ) ∗ A ( m , m ) ∗ C ( n + 2 , m ) A(n+2,n+2) * A(m,m) * C(n+3,m) - A(2,2) * A(n+1,n+1) * A(m,m) * C(n+2,m) A(n+2,n+2)∗A(m,m)∗C(n+3,m)−A(2,2)∗A(n+1,n+1)∗A(m,m)∗C(n+2,m)
化简得到:
代码:
import java.math.BigInteger;
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(), m = sc.nextInt();
if (m>n+3||m+n==0) { //没有合适方案的情况
System.out.println(0);
return;
}
BigInteger l = new BigInteger("1");//存左边公式的结果
BigInteger r = new BigInteger("2");//存右边公式的结果
for (int i = 1; i <= n+2; i++) // (n+2)!
l = l.multiply(BigInteger.valueOf(i));
for (int i = n+3; i > n+3-m; i--) //(n+2)!(n+3)!/(n+3-m)!
l = l.multiply(BigInteger.valueOf(i));
for (int i = 1; i <= n+1; i++) // 2*(n+1)!
r = r.multiply(BigInteger.valueOf(i));
for (int i = n+2; i > n+2-m; i--) // 2*(n+1)!(n+2)!/(n+2-m)!
r = r.multiply(BigInteger.valueOf(i));
System.out.println(l.subtract(r));//输出相减之后的结果
}
}