题意:有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. Scrapy使用RabbitMQ做任务队列

    前言 一个月没更博客了,这个月也搞了不少东西,但是公司对保密性要求挺高,很多东西都没有办法写出来 想来想去,还是写一篇最近写Scrapy中遇到的跳转问题 如果你的业务需求是遇到301/302/303跳 ...

  2. 【JavaWeb】XML 文件

    XML 文件 简介 XML 是可拓展的标记性语言. XML 的主要作用: 用来保存数据,且这些数据具有自我描述性: 作为项目或模块的配置文件: 作为网络数据传输的格式,但是现在以 JSON 格式为主. ...

  3. docker基础总结

    搜索镜像docker search ubuntu 搜索ubuntu的Docker镜像 搜索结果单个单词ubuntu这样的镜像,被称为基础镜像或根镜像,这些基础镜像由 Docker 公司创建搜索结果ti ...

  4. 搭乘“AI大数据”快车,肌肤管家,助力美业数字化发展

    经过疫情的发酵,加速推动各行各业进入数据时代的步伐.美业,一个通过自身技术.产品让用户变美的行业,在AI大数据的加持下表现尤为突出. 对于美妆护肤企业来说,一边是进入存量市场,一边是疫后的复苏期,一边 ...

  5. Centos 6.5 Rabbitmq 安装和集群,镜像部署

    centos 6.5 rabbitmq 安装和集群,镜像部署 安装erlang: yum install gcc glibc-devel make ncurses-devel openssl-deve ...

  6. 【Linux】ssh互信脚本

    使用互信脚本的时候,需要敲回车,但是shell脚本无法满足,所以需要用到expect脚本 rpm -qa | grep expect 如果没有的话,直接用yum安装即可 yum install exp ...

  7. DNS基础概要

    dns服务系统由客户端和服务器组成,提供域名到ip地址的解析,或者提供ip地址到域名的逆向解析. 1.DNS域名空间 每个dns域名由分级的label构成,如www.sina.com.cn,由www. ...

  8. Databricks 第7篇:管理Secret

    有时,访问数据要求您通过JDBC对外部数据源进行身份验证,可以使用Azure Databricks Secret来存储凭据,并在notebook和job中引用它们,而不是直接在notebook中输入凭 ...

  9. LOOP语句的AT语句块

    在loop一个内表的时候,如果想在loop循环中使用AT NEW ,AT END OF 等语句,一定需要注意的几点: 1.内表要排序 2.AT END OF 语句中影响的是指定字段前面所有的字段 3. ...

  10. C++:标准I/O流

    标准I/O对象:cin,cout,cerr,clog cout; //全局流对象 输出数据到显示器 cin; //cerr没有缓冲区 clog有缓冲区 cerr; //标准错误 输出数据到显示器 cl ...