[HNOI2012]排队

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

题解:

$$Ans=A{^n_n}×A{^2_{n+1}}×A{^m_{n+3}}+A{^n_n}×A{^1_{n+1}}×A{^2_2}×A{^1_m}×A{^{m-1}_{n+2}}$$

无脑高精度,代码瞬间一百行。。。

  1 //Never forget why you start
  2 #include<iostream>
  3 #include<cstdio>
  4 #include<cstdlib>
  5 #include<cstring>
  6 #include<cmath>
  7 #include<algorithm>
  8 #define mod (100000000)
  9 using namespace std;
 10 typedef long long lol;
 11 int n,m;
 12 struct big_num {
 13     lol f[2005];
 14     big_num() {
 15         memset(f,0,sizeof(f));
 16     }
 17     void clean() {
 18         memset(f,0,sizeof(f));
 19     }
 20     void give(lol x) {
 21         lol i;
 22         for(i=1; x; i++) {
 23             f[i]=x%mod;
 24             x/=mod;
 25         }
 26         f[0]=i-1;
 27     }
 28     friend big_num operator + (const big_num a,const big_num b) {
 29         lol j=0,to=max(a.f[0],b.f[0]);
 30         big_num ans;
 31         for(lol i=1; i<=to; i++) {
 32             ans.f[i]=a.f[i]+b.f[i]+j;
 33             if(ans.f[i]>=mod) {
 34                 j=ans.f[i]/mod;
 35                 ans.f[i]%=mod;
 36                 if(i==to)to++;
 37             } else j=0;
 38         }
 39         ans.f[0]=to;
 40         return ans;
 41     }
 42     friend big_num operator * (const big_num a,const big_num b) {
 43         lol k=0,to=0,end=0;
 44         big_num ans;
 45         for(lol i=1; i<=a.f[0]; i++) {
 46             k=0;
 47             to=b.f[0];
 48             for(lol j=1; j<=to; j++) {
 49                 ans.f[i+j-1]+=a.f[i]*b.f[j]+k;
 50                 end=max(end,i+j-1);
 51                 if(ans.f[i+j-1]>=mod) {
 52                     k=ans.f[i+j-1]/mod;
 53                     ans.f[i+j-1]%=mod;
 54                     if(j==to)to++;
 55                 } else k=0;
 56             }
 57         }
 58         ans.f[0]=end;
 59         return ans;
 60     }
 61     friend big_num operator / (const big_num a,const lol b) {
 62         lol to=a.f[0],k=0,end=0;
 63         big_num ans;
 64         for(lol i=to; i>=1; i--) {
 65             lol s=k*mod+a.f[i];
 66             ans.f[i]=s/b;
 67             if(ans.f[i])end=max(end,i);
 68             k=s%b;
 69         }
 70         ans.f[0]=end;
 71         return ans;
 72     }
 73 };
 74 char s[2005];
 75 big_num read() {
 76     lol i,j,len,cnt=0;
 77     big_num ans;
 78     scanf("%s",s+1);
 79     len=strlen(s+1);
 80     for(i=len; i>=1; i-=8) {
 81         cnt++;
 82         j=i-7;
 83         if(j<=1)j=1;
 84         for(j; j<=i; j++) {
 85             ans.f[cnt]=ans.f[cnt]*10+s[j]-‘0‘;
 86         }
 87     }
 88     ans.f[0]=cnt;
 89     return ans;
 90 }
 91 void print(big_num ans) {
 92     printf("%lld",ans.f[ans.f[0]]);
 93     lol i=ans.f[0]-1;
 94     for(i; i>=1; i--) {
 95         lol tot=mod/10;
 96         while(ans.f[i]<tot) {
 97             printf("0");
 98             tot/=10;
 99         }
100         if(ans.f[i]!=0)printf("%lld",ans.f[i]);
101     }
102     printf("\n");
103 }
104 big_num A(lol n,lol m) {
105     big_num ans,x;
106     ans.give(1ll);
107     x.clean();
108     for(lol i=n; i>=n-m+1; i--) {
109         x.give(i);
110         ans=ans*x;
111     }
112     return ans;
113 }
114 int main() {
115     lol n,m;
116     scanf("%lld%lld",&n,&m);
117     big_num 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);
118     print(Ans);
119     return 0;
120 }

原文地址:https://www.cnblogs.com/huangdalaofighting/p/8260225.html

时间: 2024-11-13 06:49:38

[HNOI2012]排队的相关文章

【BZOJ2729】[HNOI2012]排队 组合数

[BZOJ2729][HNOI2012]排队 Description 某中学有 n 名男同学,m 名女同学和两名老师要排队参加体检.他们排成一条直线,并且任意两名女同学不能相邻,两名老师也不能相邻,那么一共有多少种排法呢?(注意:任意两个人都是不同的) Input 只有一行且为用空格隔开的两个非负整数 n 和 m,其含义如上所述. 对于 30%的数据 n≤100,m≤100 对于 100%的数据 n≤2000,m≤2000 Output 输出文件 output.txt 仅包含一个非负整数,表示不

2729: [HNOI2012]排队

2729: [HNOI2012]排队 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 957  Solved: 449[Submit][Status] Description 某中学有 n 名男同学,m 名女同学和两名老师要排队参加体检.他们排成一条直线,并且任意两名女同学不能相邻,两名老师也不能相邻,那么一共有多少种排法呢?(注意:任意两个人都是不同的) Input 只有一行且为用空格隔开的两个非负整数 n 和 m,其含义如上所述. 对于 30%

[BZOJ 2729][HNOI2012]排队(排列组合+高精)

Description 某中学有 n 名男同学,m 名女同学和两名老师要排队参加体检.他们排成一条直线,并且任意两名女同学不能相邻,两名老师也不能相邻,那么一共有多少种排法呢?(注意:任意两个人都是不同的) Solution 好像必须写压位高精的QAQ 先排n名男生,插空,讨论两名老师插在两个不同的空里的情况和先排在一起再在中间插一名女生的情况 #include<iostream> #include<cstdio> #include<cstring> #include&

【BZOJ】2729: [HNOI2012]排队

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2729 先考虑放好男生,一共有:${n!}$种放法. 然后分情况考虑老师的放法: 1.如果两个老师放在了相同两个男生之间:${m*A_{n+1}^{1}*A_{n+2}^{m-1}}$ 2.如果分开放:${A_{n+1}^{2}*A_{n+3}^{m}}$ 最后答案分别与${n!}$相乘再相加即可. HNOI居然会考送肉组合数学裸题... python大发好!

bzoj2729: [HNOI2012]排队

高精度+排列组合. 如果计算老师能挨在一起的情况 有 (n+2)! * A(n+3,m) 老师一定挨宰一起的情况 有 2*(n+1)!*A(n+2,m). 相减就是答案. #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 3000; const int mod = 10000; struct bigint { int a[maxn+10

BZOJ 2729 HNOI2012 排队 组合数学

题目大意:给定n个男生m个女生两个老师,求有多少种排列满足任意两个女生不相邻,任意两个老师也不相邻 def A(n): re=1 for i in range(1,n+1): re*=i return re def C(n,m): if n<m: return 0 return A(n)//A(m)//A(n-m) n,m=[int(i) for i in raw_input().split()] print m*A(n+1)*2*A(m-1)*C(n+2,m-1)+(A(n+2)-A(n+1)

【BZOJ】【2729】【HNOI2012】排队

排列组合+高精度 Orz PoPoQQQ 引用题解: 嗯……学习了一下python= =懒的写高精了 1 /************************************************************** 2 Problem: 2729 3 User: Tunix 4 Language: Python 5 Result: Accepted 6 Time:832 ms 7 Memory:6360 kb 8 ********************************

【BZOJ2729】【HNOI2012】排队 组合数 数论 Python高精度

转载请注明出处谢谢:http://blog.csdn.net/vmurder/article/details/42964151 题解: 代码里面有注释. 注意: Python2中的中文字符即使注释了,也会CE(当然,因为Python是直接运行,不编译,所以显示WA) 呃,而本地的Python3就不管它了.. 所以我的代码需要删掉中文注释再交233. 代码: # n!(A(n+1,2)*A(n+3,m)+2*(n+1)*A(n+2,m-1)*m) # 首先男生随便放 这样是n!种摆法. # 然后再

BZOJ 2730:[HNOI2012]矿场搭建(割点+连通块)

[HNOI2012]矿场搭建 Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口.请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数.Input 输入文件有若干组数据,每组数据的第一行是一个正整数 N(N≤500),表示工地的隧道数,接下来的 N 行每行是用空