Regular Words
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 379 Accepted Submission(s): 169
Problem Description
Consider words of length 3n over alphabet {A, B, C} . Denote the number of occurences of A in a word a as A(a) , analogously let the number of occurences of B be denoted as B(a), and the number of occurenced of C as C(a) .
Let us call the word w regular if the following conditions are satisfied:
A(w)=B(w)=C(w) ;
if c is a prefix of w , then A(c)>= B(c) >= C(c) .
For example, if n = 2 there are 5 regular words: AABBCC , AABCBC , ABABCC , ABACBC and ABCABC .
Regular words in some sense generalize regular brackets sequences (if we consider two-letter alphabet and put similar conditions on regular words, they represent regular brackets sequences).
Given n , find the number of regular words.
Input
There are mutiple cases in the input file.
Each case contains n (0 <= n <= 60 ).
There is an empty line after each case.
Output
Output the number of regular words of length 3n .
There should be am empty line after each case.
Sample Input
2
3
Sample Output
5
42
动态规划计数 + 高精度 , 不懂写 Java 大数 , 杯具了好久 .
#include<stdio.h> #include<stdlib.h> #include<string.h> #define N 62 #define LL long long char dp[N][N][N][100],res[100]; int min(int a,int b) { return a<b?a:b; } int max(int a,int b) { return a>b?a:b; } void add(char a[],char b[]) { int lena,lenb,t,i,j,l; lena=strlen(a); lenb=strlen(b); char c[100]; l=max(lena,lenb)+2; memset(c,0,sizeof(c)); t=-1; i=lena-1; j=lenb-1; while(i>=0 && j>=0) { c[++t]=a[i]+b[j]-'0'; i--; j--; } if (i>=0) while (i>=0) { c[++t]=a[i]; i--; } else while (j>=0) { c[++t]=b[j]; j--; } for (i=0; i<=t; ++i) { if (c[i]-'0'>=10) { c[i]-=10; if (i!=t) c[i+1]++; else { c[i+1]='1'; ++t; } } } memset(a,0,sizeof(a)); for (i=0; i<=t; ++i) a[i]=c[t-i]; a[t+1]='/0'; } int main() { int n,len,i,j,k,l,a,b,tt; strcpy(dp[0][0][0],"1/0"); strcpy(dp[1][0][0],"1/0"); strcpy(dp[0][1][0],"0/0"); strcpy(dp[0][0][1],"0/0"); strcpy(dp[1][1][0],"1/0"); strcpy(dp[0][1][1],"0/0"); strcpy(dp[1][0][1],"0/0"); for (i=1; i<=60; ++i) { for (j=0; j<=i; ++j) { for (k=0;k<=j;++k) { strcpy(res,"0/0"); if (i>=j && j>=k) { if (i>j && j>=k) add(res,dp[i-1][j][k]); if (j>k && i>=j) add(res,dp[i][j-1][k]); if (k>0 && i>=j && j>=k) add(res,dp[i][j][k-1]); } strcpy(dp[i][j][k],res); } } } while (scanf("%d",&n)!=EOF) { if (n==0) { printf("0/n/n"); continue; } puts(dp[n][n][n]); printf("/n"); } return 0; }