题意:有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. 10步写了个Django网站,正经网站···

      Django做网站只要10步,真的只有10步,不信?咱们来数数--   今天主要讲解用Pycharm编辑器搭建网站,网站功能是 实现在局域网中快速传递大文件! 比如:同事要给你个1G的文件,你丢一 ...

  2. win7安装oracle11g和oracle client和pl/sql

    一.安装oracle11g 1.下载Oracle 11g R2 for Windows的版本 下载地址:hhttps://www.oracle.com/technetwork/database/ent ...

  3. 为linux添加一块新硬盘并分区

    一---如何增加一块硬盘1:虚拟机添加硬盘2:分区3:格式化4:挂载5:设置可以自动挂载 1---设置里面 2---分区命令 fdisk /dev/sdb开始分区m显示命令列表p显示磁盘分区 同fdi ...

  4. CopyOnWriteArrayList 读写分离,弱一致性

    为什么会有CopyOnWriteArrayList? 我们知道ArrayList和LinkedList实现的List都是非线程安全的,于是就有了Vector,它是基于ArrayList的线程安全集合, ...

  5. Java高并发与多线程(二)-----线程的实现方式

    今天,我们开始Java高并发与多线程的第二篇,线程的实现方式. 通常来讲,线程有三种基础实现方式,一种是继承Thread类,一种是实现Runnable接口,还有一种是实现Callable接口,当然,如 ...

  6. 如何跑通第一个 SQL 作业

    简介: 本文由阿里巴巴技术专家周凯波(宝牛)分享,主要介绍如何跑通第一个SQL. 一.SQL的基本概念 1.SQL 分类 SQL分为四类,分别是数据查询语言(DQL).数据操纵语言(DML).数据定义 ...

  7. CTFHub - Web(四)

    最近又是每天忙到裂开,,,淦 xss: 反射型: 1.第一个输入框与下面Hello后的内容相同,猜测可以通过该输入,改变页面内容. 测试语句: <script>alert(1)</s ...

  8. ctfhub技能树—web前置技能—http协议—请求方式

    打开靶机环境(每次打开都要30金币,好心疼啊) 题目描述为"请求方式" HTTP的请求方式共有八种 1.OPTIONS 返回服务器针对特定资源所支持的HTTP请求方法,也可以利用向 ...

  9. Android 代码规范大全

    前言 虽然我们项目的代码时间并不长,也没经过太多人手,但代码的规范性依然堪忧,目前存在较多的比较自由的「代码规范」,这非常不利于项目的维护,代码可读性也不够高, 此外,客户端和后端的研发模式也完全不同 ...

  10. 利用JavaUDPSocket+多线程模拟实现一个简单的聊天室程序

    对Socket的一点个人理解:Socket原意是指插座.家家户户都有五花八门的家用电器,但它们共用统一制式的插座.这样做的好处就是将所有家用电器的通电方式统一化,不需要大费周章地在墙壁上凿洞并专门接电 ...