标签:
【分析】
当m<n,显然一定不合法。
所以我们考虑m>=n,类比n=m时的方案数推法,总方案为C(m,m+n),要减去不符合的情况。
我们扫描一个数,找到第一个不符合的位置,假设是有a个1,a+1个1,那么我们后面会填n-a-1个-1,m-a个1,我们把后面的1和-1交换,就得到了一个有m-a个-1,n-a-1个1的数,方案为C(m+1,m+n),把它减掉即可,
即ans=C(m,m+n)-C(m+1,m+n)。因为每个人不相同最后1还要乘n!*m!。
为什么要用1和-1互换呢,
首先对于一个不合法串是唯一对应一个转换串的(就按照上述方法转换),
然后对于一个转换串是一定对应一个不合法串的,方法是找到其第一个不合法的地方,然后后面部分-1和1转换。
还有就是转换串一定不合法,因为它有m+1个-1,n-1个1,而m>=n。这就是他比原串优越的地方,用他可以完全取代不合法串!
代码如下:(还没有测,hdu挂掉了)
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<queue> 7 #include<cmath> 8 using namespace std; 9 #define Maxn 110 10 11 struct node 12 { 13 int d[Maxn],ln; 14 }; 15 node t[3]; 16 17 void mul(int x,int y) 18 { 19 int add=0; 20 for(int i=1;i<=t[x].ln;i++) 21 { 22 t[x].d[i]*=y; 23 t[x].d[i]+=add; 24 add=t[x].d[i]/10; 25 t[x].d[i]%=10; 26 // if(i==t[x].ln&&t[x].d[i+1]!=0) t[x].ln++; 27 } 28 t[x].d[t[x].ln+1]=add; 29 while(t[x].d[t[x].ln+1]!=0) 30 { 31 t[x].ln++; 32 t[x].d[t[x].ln+1]=t[x].d[t[x].ln]/10; 33 t[x].d[t[x].ln]%=10; 34 } 35 } 36 37 void get_ans() 38 { 39 t[2].ln=t[0].ln; 40 for(int i=1;i<=t[0].ln;i++) 41 { 42 if(t[0].d[i]<t[1].d[i]) 43 { 44 t[0].d[i+1]--; 45 t[0].d[i]+=10; 46 } 47 t[2].d[i]=t[0].d[i]-t[1].d[i]; 48 } 49 while(t[2].d[t[2].ln]==0) t[2].ln--; 50 if(t[2].ln==0) t[2].ln++; 51 } 52 53 int main() 54 { 55 int kase=0; 56 while(1) 57 { 58 int m,n; 59 scanf("%d%d",&m,&n); 60 if(m==0&&n==0) break; 61 printf("Test #%d:\n",++kase); 62 if(m<n) {printf("0\n");continue;} 63 memset(t[0].d,0,sizeof(t[0].d)); 64 memset(t[1].d,0,sizeof(t[1].d)); 65 t[0].d[1]=1; t[0].ln=1; 66 for(int i=1;i<=m+n;i++) 67 { 68 mul(0,i); 69 } 70 t[1].d[1]=1; t[1].ln=1; 71 for(int i=1;i<=m;i++) 72 { 73 mul(1,i); 74 } 75 for(int i=m+2;i<=m+n;i++) 76 { 77 mul(1,i); 78 } 79 mul(1,n); 80 get_ans(); 81 for(int i=t[2].ln;i>=1;i--) printf("%d",t[2].d[i]); 82 printf("\n"); 83 } 84 return 0; 85 }
2016-09-07 22:06:16
【HDU 1133】 Buy the Ticket (卡特兰数)
标签:
原文地址:http://www.cnblogs.com/Konjakmoyu/p/5851273.html