這玩意不是卡特蘭的經典模型嗎……ios
咱們設方案數爲f(i),則f(0)=1,f(1)=1,f(2)=2,f(3)=5,(其實到這裏你再手模一個就出來了)咱們把左上角的矩形刪掉,則會變成下方和右方兩個更小規模的問題(若是沒有就是f(0)嘍),拿樣例舉例f(3)=f(2)的一種狀況*f(0)+f(2)的另外一種狀況*f(0)+f(1)*f(1)+f(0)*f(2)的一種狀況+f(0)*f(2)的另外一種狀況,總結一下,f(3)=$∑_{i=0}^{2}f(i)*f(2-i)$,對全部狀況進行概括,則獲得Cat數O(n^2)的那個遞歸的式子。ide
至於算的時候,直接O(n)惟一分解接高精就搞定了,(至於你不懂什麼叫O(n)惟一分解,你能夠去看代碼或上一篇博客)。spa
#include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<cstdio> #include<vector> #include<queue> #include<stack> #include<set> #include<map> using namespace std; int n,prime[1000],prime_num; bool v[1050]; struct Bigint{ int a[10000],len; void clear(){ memset(a,0,sizeof(a)); len=1; a[1]=1; } friend void operator *(Bigint &x,int y){ int delta=0; for(int i=1;i<=x.len;i++){ x.a[i]=x.a[i]*y+delta; delta=x.a[i]/10; x.a[i]%=10; } while(delta>0){ x.a[++x.len]=delta%10; delta/=10; } while(x.a[x.len]==0&&x.len>1) --x.len; } void out(){ for(int i=len;i>=1;i--) printf("%d",a[i]); } }ans; void doprime(int x){ for(int i=2;i<=x;i++){ if(!v[i]) prime[++prime_num]=i; for(int j=1;j<=prime_num&&i*prime[j]<=x;j++){ v[i*prime[j]]=1; if(i%prime[j]==0) break; } } } int main(){ scanf("%d",&n); doprime(2*n+2);ans.clear(); for(int i=1;i<=prime_num;i++){ long long s=0; for(int j=2*n;j/=prime[i];) s+=j; for(int j=n;j/=prime[i];) s-=j; for(int j=n+1;j/=prime[i];) s-=j; for(int j=1;j<=s;j++) ans*prime[i]; } ans.out(); return 0; }
至此Cat三題吸取完畢。code