[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 }

 

posted @ 2017-10-08 09:20  Z-Y-Y-S  阅读(250)  评论(0编辑  收藏  举报