题意:有m个人有一张50元的纸币,n个人有一张100元的纸币。他们要在一个原始存金为0元的售票处买一张50元的票,问一共有几种方案数。

解法:(学习了他人的推导后~)

1.Catalan数的应用7的变形。(推荐阅读:http://www.cnblogs.com/chenhuan001/p/5157133.html)。P.S.不知我之前自己推出的公式“C(n,m)*C(2*m,m)/(m+1)*P(n,n)*P(m,m)”是否是正确的。

(1)在不考虑m人和n人本身组内的排列时,总方案数为C(m+n,n)或C(m+n,m)。

(2)而不合法的设1为50元(m个),0为100元(n个)。那么便有10110...设前2k+1个数中有k+1个0和k个1,因此不合法。而将2k+1之后的所有0(n-k-1个)和1(m-k个)异或。这样的转换是唯一对应的,不合法的方案数仍不会改变,因此可行,得到n-k-1个1和m-k个0。总共n-1个1和m+1个0。这样不合法的方案数就可用C(n+m,n-1)或C(n+m,m+1)表示了。

由于(1)-(2)已经包含了m人和n人跨组之间的组合,于是只乘上m人和n人本身组内的排列P(m,m)和P(n,n)表示答案,而不是P(n+m,n+m)。化简可得(m+n)! (m-n+1)/(m+1)。

2.隔板法。(不知道这个方法是不是这么叫......)

(1)先放了n个5元,构成n+1个空位。再一个个放m个100元,第一个,除了第1个空不可,其它位置都可放,合法的概率为n/(n+1)。第二个100元,概率变为(n-1)/n。以此类推,第m个的概率就是(n-m+1)/(n-m+2)。那么这m个100元的合法的总概率就是所有的概率相乘,得到(n-m+1)/(n+1)。

(2)然后再考虑这n+m个的排列方法P(n+m,n+m),与原来的相乘。

最终得到(n+m)!*(n-m+1)/(n+1).

 1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<iostream>
5 using namespace std;
6 #define N 110
7
8 struct node
9 {
10 int s[510];
11 int l;
12 node() {l=0;memset(s,0,sizeof(s));}
13 };
14 node multi(node x,int y)//dif from +
15 {
16 node z;
17 z.l=x.l;
18 for (int i=1;i<=x.l;i++)
19 {
20 z.s[i]+=x.s[i]*y;
21 if (z.s[i]>9) z.s[i+1]+=z.s[i]/10,z.s[i]%=10;
22 }
23 while (z.s[z.l+1])
24 {
25 z.l++;
26 if (z.s[z.l]>9) z.s[z.l+1]+=z.s[z.l]/10,z.s[z.l]%=10;
27 }
28 return z;
29 }
30 node conv(node x)
31 {
32 node z;
33 z.l=x.l;
34 for (int i=1;i<=x.l;i++)
35 z.s[x.l-i+1]=x.s[i];
36 return z;
37 }
38 node div(node x,int y)
39 {
40 node z;
41 int t=x.l+1,h=0;
42 while (h<y && t>1) h=10*h+x.s[--t];
43 z.s[++z.l]=h/y,h%=y;
44 while (t>1)
45 {
46 h=10*h+x.s[--t];
47 z.s[++z.l]=h/y,h%=y;
48 }
49 z=conv(z);
50 return z;
51 }
52 /*另一种打法
53 node div(node x,int y)//crucial
54 {
55 node z;
56 int t=x.l+1,h=0;
57 while (t>1)//converse!
58 {
59 bool tf=true;
60 while (h<y && t>1)
61 {
62 h=10*h+x.s[--t];
63 if (!tf&&z.l) z.s[++z.l]=0;//商最高位之后才开始赋值0,并且要是加入新的一位为0
64 tf=false;
65 }
66 z.s[++z.l]=h/y,h%=y;
67 }
68 z=conv(z);
69 return z;
70 }
71 */
72 void print(node x)
73 {
74 for (int i=x.l;i>=1;i--)
75 printf("%d",x.s[i]);
76 printf("\n");
77 }
78 node P(int x)
79 {
80 node z;
81 z.l=z.s[1]=1;
82 for (int i=x;i>=1;i--)
83 z=multi(z,i);
84 return z;
85 }
86 int main()
87 {
88 int n,m;
89 while (1)
90 {
91 scanf("%d%d",&n,&m);
92 if (!n&&!m) break;
93 if (n<m) {printf("0\n");continue;}
94 print(div(multi(P(n+m),n-m+1),n+1));
95 }
96 return 0;
97 }

排列组合+高精度

3.动态规划。转载自:http://blog.csdn.net/clover_hxy/article/details/52931233

f[i][j]表示到第i个人,已经有j个人用50元买了门票。
f[i][j] = f[i-1][j] + f[i-1][j-1]; (当前这个人分别用100元或50元。同时用 k=i-j 表示100元的个数,递推时保证 k<=j。)
因为每个人是不一样的所以最后的答案是 f[n+m][n]*n!*m!。

P.S.看!DP一个状态递推就能省了上面2种一长串的头脑风暴推导过程,可见DP的优越性。

  1 #include<iostream>
2 #include<algorithm>
3 #include<cstring>
4 #include<cstdio>
5 #include<cmath>
6 #define N 103
7 using namespace std;
8 struct data{
9 int num[403];
10 }f[N*2][N],ans;
11 int n,m,a[N],b[N],c[N];
12 int calc(int a[N],int x)
13 {
14 a[0]=1; a[1]=1;
15 for (int i=1;i<=x;i++)
16 {
17 for (int j=1;j<=a[0];j++)
18 a[j]*=i;
19 for (int j=1;j<=a[0];j++) {
20 a[j+1]+=a[j]/10000;
21 a[j]%=10000;
22 }
23 int t=a[0];
24 while (a[t+1]) {
25 t++;
26 a[t+1]+=a[t]/10000;
27 a[t]%=10000;
28 }
29 a[0]=t;
30 }
31 }
32 void add(data &x,data y,data z)
33 {
34 int t=max(y.num[0],z.num[0]);
35 for (int i=1;i<=t;i++)
36 x.num[i]=y.num[i]+z.num[i];
37 for (int i=1;i<=t;i++)
38 x.num[i+1]+=x.num[i]/10000,x.num[i]%=10000;
39 while (x.num[t+1]){
40 t++;
41 x.num[t+1]+=x.num[t]/10000;
42 x.num[t]%=10000;
43 }
44 x.num[0]=t;
45 }
46 void mul(data &x,int a[N])
47 {
48 memset(c,0,sizeof(c));
49 for (int i=1;i<=x.num[0];i++)
50 for (int j=1;j<=a[0];j++)
51 c[i+j-1]+=x.num[i]*a[j];
52 int t=max(x.num[0],a[0]);
53 for (int i=1;i<=t;i++)
54 c[i+1]+=c[i]/10000,c[i]%=10000;
55 while(c[t+1]) {
56 t++;
57 c[t+1]+=c[t]/10000;
58 c[t]%=10000;
59 }
60 c[0]=t;
61 for (int i=0;i<=c[0];i++) x.num[i]=c[i];
62 }
63 int main()
64 {
65 freopen("a.in","r",stdin);
66 freopen("my.out","w",stdout);
67 int n=100; int m=100;
68 f[0][0].num[0]=1;
69 f[0][0].num[1]=1;
70 for (int i=1;i<=n+m;i++)
71 for (int j=min(i,n);j>=1;j--)
72 {
73 int k=(i-j);
74 if (k>j) break;
75 add(f[i][j],f[i-1][j],f[i-1][j-1]);
76 }
77 int cnt=0;
78 while (true){
79 scanf("%d%d",&n,&m); cnt++;
80 if (n==0&&m==0) break;
81 memset(a,0,sizeof(a));
82 memset(b,0,sizeof(b));
83 calc(a,n); calc(b,m);
84 for (int i=0;i<=400;i++) ans.num[i]=0;
85 for (int i=0;i<=f[n+m][n].num[0];i++)
86 ans.num[i]=f[n+m][n].num[i];
87 mul(ans,a); mul(ans,b);
88 printf("Test #%d:\n",cnt);
89 if (ans.num[0]==0||n<m) {
90 printf("0\n");
91 continue;
92 }
93 for (int i=ans.num[0];i>=1;i--){
94 int t=ans.num[i];
95 if (i!=ans.num[0]){
96 if (t<10) printf("000");
97 else if (t<100) printf("00");
98 else if (t<1000) printf("0");
99 }
100 printf("%d",t);
101 }
102 printf("\n");
103 }
104 }

DP+压位高精度

【noi 2.6_9288】&【hdu 1133】Buy the Ticket(DP / 排列组合 Catalan+高精度除法)的更多相关文章

  1. hdu 1133 Buy the Ticket(Catalan)

    Buy the Ticket Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) T ...

  2. hdu 1133 Buy the Ticket (大数+递推)

    Buy the Ticket Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)To ...

  3. HDU——1133 Buy the Ticket

    Buy the Ticket Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) T ...

  4. HDU 1133 Buy the Ticket (数学、大数阶乘)

    Buy the Ticket Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)To ...

  5. hdu 1133 Buy the Ticket

    首先,记50的为0,100的为1. 当m=4,n=3时,其中的非法序列有0110010; 从不合法的1后面开始,0->1,1->0,得到序列式0111101 也就是说,非法序列变为了n-1 ...

  6. HDOJ/HDU 1133 Buy the Ticket(数论~卡特兰数~大数~)

    Problem Description The "Harry Potter and the Goblet of Fire" will be on show in the next ...

  7. HDU 1133 Buy the Ticket 卡特兰数

    设50元的人为+1 100元的人为-1 满足前随意k个人的和大于等于0 卡特兰数 C(n+m, m)-C(n+m, m+1)*n!*m! import java.math.*; import java ...

  8. HDU 4043 FXTZ II (组合数学-排列组合)

    FXTZ II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Su ...

  9. HDU 5151 Sit sit sit 区间DP + 排列组合

    Sit sit sit 问题描述 在一个XX大学中有NN张椅子排成一排,椅子上都没有人,每张椅子都有颜色,分别为蓝色或者红色. 接下来依次来了NN个学生,标号依次为1,2,3,...,N. 对于每个学 ...

随机推荐

  1. 【JavaWeb】Filter 过滤器

    Filter 过滤器 简介 Filter 过滤器是 JavaWeb 三大组件之一 Filter 过滤器是 JavaEE 的规范,也就是接口 Filter 过滤器的作用是 拦截请求,过滤响应 拦截请求的 ...

  2. 阿里云OSS整合

    一.对象存储OSS 为了解决海量数据存储与弹性扩容(主要是静态文件的存储例如图片,语音,视频等),项目中我们通常采用云存储的解决方案- 阿里云OSS. 1.开通"对象存储OSS"服 ...

  3. Spark学习进度11-Spark Streaming&Structured Streaming

    Spark Streaming Spark Streaming 介绍 批量计算 流计算 Spark Streaming 入门 Netcat 的使用 项目实例 目标:使用 Spark Streaming ...

  4. centos 6.5 下安装RabbitMQ-3.7.28 二进制版本

    centos 6.5 下安装RabbitMQ-3.7.28 二进制版本 安装依赖: yum install -y ncurses-devel socat logrotatewxWidgets-deve ...

  5. Docker Harbor 高可用 1.7.5版本(七)

    环境说明: node1 10.10.5.135 仓库 1 node2 10.10.5.136 仓库 2 node3 10.10.5.137 客户端 实验内容: Harbor 可以在两台主机之间相互同步 ...

  6. 5.1中repair table

    mysql> repair table xs;+---------+--------+----------+----------+| Table | Op | Msg_type | Msg_te ...

  7. row和statement

    [root@ma bin]# /usr/local/mysql/bin/mysqlbinlog -vv /var/lib/bin/mysql-bin.000013 --base64-output=DE ...

  8. CTFHub - Web(一)

    请求方法: 1.进入页面,提示:HTTP 请求方法, HTTP/1.1协议中共定义了八种方法(也叫动作)来以不同方式操作指定的资源. 2.当前http的请求方式是get请求,当你使用CTFHUB为请求 ...

  9. VL02N发货过账BAPI

    使用BAPI函数: BAPI_OUTB_DELIVERY_CONFIRM_DEC 进行delivery的发货过账,可能会有如此的需求,就是修改实际的发货日期.规划的GI.交货日期.装载日期.传输计划日 ...

  10. 安装jdk-windows系统

    1. 明确需要安装的jdk版本,注意jdk存在小版本号,例如jdk1.7_51,如果不清楚小版本号的话建议安装最新版本的jdk: 2. 打开cmd命令窗口,输入java -version查看本机是否安 ...