1. 程式人生 > >HDU 3723 Delta Wave(2010 Asia Tianjin Regional Contest )

HDU 3723 Delta Wave(2010 Asia Tianjin Regional Contest )

【解題報告】
結論題,知道是卡特蘭數的話就會很好寫。
我們知道最後偏移量為0,所以假如向上偏移一次,就一定會有對應的向下偏移一次。這類似一個入棧出棧操作。
假如有i次入棧,那麼對應的i個數的出棧序列為:

    2*C(  2i,n )*Cat(i).

其中:

    cat(i)=cat(i-1)*2(2i-1)/(i+1);

化簡公式得到遞推式為:

    ans[i]/ans[i-1]=(n-2i+2)*(n-2i+1)/(i*(i-1));

然後高精度遞推計算,累加ans[i]即可。

【參考程式碼】

#include<iostream>
#include<cstdio> #include<cstring> using namespace std; const int maxn=100000; int C[maxn],ans[maxn]; int n,len; int main() { while( ~scanf("%d",&n) ) { memset(C,0,sizeof(C)); memset(ans,0,sizeof(ans)); C[1]=1; len=1; //i=0的時候 ans[1]=1; //i=0的時候 for
( int i=1; i*2<=n; i++ ) { for( int j=1; j<=len; j++ ) C[j]*=(n-2*i+2)*(n-2*i+1); for( int j=1; j<len; j++ ) if(C[j]>9){ C[j+1]+=C[j]/10; C[j]%=10; } while( C[len]>10 )//進位 { C[len+1]=C[len]/10; C[len]%=10
; len++; } for( int j=len; j>=1; j-- ) { if( C[j]/(i*(i+1))==0 ) { C[j-1]+=C[j]*10; C[j]=0; if(len==j)len--; } else { C[j-1]+=C[j]%(i*(i+1))*10; C[j]/=i*(i+1); } } for( int j=1; j<=100; j++ )ans[j]+=C[j]; for( int j=1; j<=100; j++ ) { if( ans[j]>9 ) { ans[j+1]+=ans[j]/10; ans[j]%=10; } } } int ans_len=100; while( ans[ans_len]==0 )ans_len--; for( int i=ans_len; i>=1; i-- )printf("%d",ans[i]); printf("\n"); } return 0; }