糾結 的題啊
ACMStep的2.3.8
在2.3裡一看題就往Catalan數上想了 很欣喜的推匯出了公式:C[m][n]=(m-n+1)/n*C[m][n-1]; C[m][0]=1;其中,m是D可以放置的位置數。
最後用大數的處理方式計算出了結果 提交後WA嗄 愣是想了半天不知道為何嗄
最後的最後 找了himdd的博文,發現可以用DP的思想。
解法一:DP
代碼及解析如下:
#include<iostream>using namespace std;long long num[23][23];int Calculate(){ int i,j; num[0][0]=1; //神奇的DP for(i=1;i<22;i++) { num[i][0]=1; for(j=1;j<=i;j++) num[i][j]=num[i-1][j]+num[i][j-1];//////////////////i個H和j個D可以看成是://////////////////i-1個H和j個D的串串最後補一個H//////////////////i個H和j-1個D的串串最後補一個D } return 0;}int main(){ Calculate(); int m,n; while(cin>>m>>n) { cout<<num[m][n]<<endl; } return 0;}
解法二:
Catalan思想:
C(n,m)=C(m+n,m)-C(m+n,m+1);(一般的Catalan是n與2n的關係,此題為n+m的關係)
代碼 l略
附上俺的Catalan想法及代碼:
對於m個H,n個D。可以先把H的位置固定,其中對於第一個H後可以放置1個D,第i個放置i個D,當i>n時,可放置n個D。一共num個位置可放置D。
在num個位置中選擇n個即為串串的個數。
(尚未想通為什麼不對呢)
#include<stdio.h>#include<string.h>#include<iostream>using namespace std;//公式:C[m][n]=(m-n+1)/n*C[m][n-1];////////C[m][0]=1;int C[211][21][101];int Calculate(){ int i,j,k; for(i=1;i<=210;i++) { C[i][0][0]=1; int len=1;//乘(m-n+1) for(j=1;j<=i&&j<=20;j++) { int flag=0; for(k=0;k<len;k++) { int w=(i-j+1)*C[i][j-1][k]+flag; C[i][j][k]=w%10; flag=w/10; } while(flag) { C[i][j][k++]=flag%10; flag/=10; } len=k;//除n while(k>=0) { int y=C[i][j][k]+flag*10; C[i][j][k]=y/j; flag=y%j; k--; } } } return 0;}int main(){ memset(C,0,sizeof(C)); Calculate();int m,n;int i,j;int num=0;while(cin>>m>>n){num=0;for(i=1;i<=m;i++)//計算字元D可以放置的位置{if(i<n)num+=i;else num+=n;}cout<<num<<endl;j=100;while (C[num][n][j]==0){j--;}while(j>=0)cout<<C[num][n][j--];cout<<endl;}return 0;}