HDU 3723 Delta Wave(2010 Asia Tianjin Regional Contest )
阿新 • • 發佈:2019-02-14
【解題報告】
結論題,知道是卡特蘭數的話就會很好寫。
我們知道最後偏移量為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;
}