题意:
一个单词X由{A,B,C}三种字母构成。
A(X):单词X中A的个数。B(X),C(X)同理。
一个单词X如果是regular word必须满足A(X)=B(X)=C(X)且对于X的任意前缀有A(X)>=B(X)>=C(X)。
给一个数n。问长度为3n的regular word有多少个。
思路:
dp[a][b][c]:前a+b+c个字母由a个A,b个B,c个C构成。
然后就可以分解了,,,
*:用到高精度
代码:
int const MAXN=99999999; int const DLEN=8; class BigNum{ private: int a[20]; int len; public: BigNum(){}; BigNum(const int); BigNum &operator=(const BigNum &); BigNum operator+(const BigNum &) const; void print(); }; BigNum::BigNum(const int b){ int c,d=b; len=0; mem(a,0); while(d>MAXN){ c=d-(d/(MAXN+1))*(MAXN+1); d=d/(MAXN+1); a[len++]=c; } a[len++]=d; } BigNum & BigNum::operator=(const BigNum & n){ int i; len=n.len; mem(a,0); rep(i,0,len-1) a[i]=n.a[i]; return *this; } BigNum BigNum::operator+(const BigNum & T) const{ BigNum t(*this); int i,big; big=T.len>len?T.len:len; for(int i=0;i<big;++i){ t.a[i]+=T.a[i]; if(t.a[i]>MAXN){ t.a[i+1]++; t.a[i]-=(MAXN+1); } } if(t.a[big]!=0) t.len=big+1; else t.len=big; return t; } void BigNum::print(){ int i; cout<<a[len-1]; for(i=len-2;i>=0;i--){ cout.width(DLEN); cout.fill(‘0‘); cout<<a[i]; } cout<<endl; } int n; BigNum dp[62][62][62]; int main(){ int n; while(scanf("%d",&n)!=EOF){ mem(dp,0); dp[0][0][0]=BigNum(1); rep(a,0,n){ rep(b,0,n){ rep(c,0,n){ if(a==0 && b==0 && c==0) continue; if(a>=b && b>=c){ if(a-1>=b && a>=1){ dp[a][b][c]=dp[a][b][c]+dp[a-1][b][c]; } if(b-1>=c && b>=1){ dp[a][b][c]=dp[a][b][c]+dp[a][b-1][c]; } if(c>=1){ dp[a][b][c]=dp[a][b][c]+dp[a][b][c-1]; } } } } } dp[n][n][n].print(); printf("\n"); } return 0; }
时间: 2024-10-14 04:35:38