[HNOI2012]排队
题目描述
某中学有 n 名男同学,m 名女同学和两名老师要排队参加体检。他们排成一条直线,并且任意两名女同学不能相邻,两名老师也不能相邻,那么一共有多少种排法呢?(注意:任意两个人都是不同的)
输入输出格式
输入格式:只有一行且为用空格隔开的两个非负整数 n 和 m,其含义如上所述。 对于 30%的数据 n<=100,m<=100 对于 100%的数据 n<=2000,m<=2000
输出格式:输出文件 output.txt 仅包含一个非负整数,表示不同的排法个数。注意答案可能很大。
输入输出样例
输入样例#1:
1 1
输出样例#1:
12
考虑将老师和女生放到男生中间(注意这道题每个人不一样)
男生排列方案:A(n,n)
现在有n+1个间隔,要将2个老师放入:A(n+1,2)
现在产生了n+3个间隔,将m个女生放入:A(n+3,m)
但是我们忽略了一种方案
我们算的是将老师分别放到男生中间,也就是说,隔开老师的必有一个男生
实际上可以只放一个女生
把2个老师和1个女生和为一块,放入男生中方案:n+1
放剩下的女生:A(n+2,m-1)
选出1个女生:C(m,1)
老师排列方案:A(2,2)=2
男生排列方案:A(n,n)
所以ans=A(n,n)*A(n+1,2)*A(n+3,m)+(n+1)*A(n+2,m-1)*C(m,1)*A(n,n)*2
因为不取模,所以必须要高精度
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 int ans1[100001],ans2[100001],ans[100001],len1,len2,len; 8 int n,m; 9 void calc1(int x) 10 {int i; 11 for (i=1;i<=len1;i++) 12 { 13 ans1[i]*=x; 14 } 15 for (i=1;i<=len1;i++) 16 if (ans1[i]>=10) 17 { 18 ans1[i+1]+=ans1[i]/10; 19 ans1[i]%=10; 20 } 21 while (ans1[len1+1]) 22 { 23 len1++; 24 if (ans1[len1]>=10) 25 { 26 ans1[len1+1]+=ans1[len1]/10; 27 ans1[len1]%=10; 28 } 29 } 30 } 31 void calc2(int x) 32 {int i; 33 for (i=1;i<=len2;i++) 34 { 35 ans2[i]*=x; 36 } 37 for (i=1;i<=len2;i++) 38 if (ans2[i]>=10) 39 { 40 ans2[i+1]+=ans2[i]/10; 41 ans2[i]%=10; 42 } 43 while (ans2[len2+1]) 44 { 45 len2++; 46 if (ans2[len2]>=10) 47 { 48 ans2[len2+1]+=ans2[len2]/10; 49 ans2[len2]%=10; 50 } 51 } 52 } 53 void add() 54 {int i; 55 len=max(len1,len2); 56 for (i=1;i<=len;i++) 57 ans[i]=ans1[i]+ans2[i]; 58 for (i=1;i<=len;i++) 59 if (ans[i]>=10) 60 { 61 ans[i+1]+=ans[i]/10; 62 ans[i]%=10; 63 } 64 while (ans[len+1]) 65 {len++; 66 if (ans[len]>=10) 67 { 68 ans[len+1]+=ans[len]/10; 69 ans[len]%=10; 70 } 71 } 72 } 73 int main() 74 {int i; 75 cin>>n>>m; 76 ans1[1]=1;len1=1; 77 for (i=1;i<=n;i++) 78 calc1(i); 79 calc1(n+1);calc1(n); 80 for (i=n+3;i>=n+4-m;i--) 81 calc1(i); 82 83 ans2[1]=1;len2=1; 84 calc2(n+1); 85 for (i=n+2;i>=n+4-m;i--) 86 calc2(i); 87 calc2(m); 88 for (i=1;i<=n;i++) 89 calc2(i); 90 calc2(2); 91 add(); 92 for (i=len;i>=1;i--) 93 printf("%d",ans[i]); 94 }