题目地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2711
题解:1记录num[i][j][k] 表示从第一个字符开始,长度为i+j+k的,A的个数为i,B的个数为j,C的个数为k的字符串的个数。
则如果i>=j>=k 则可以根据最后一个字符是A, B还是C,分三类计数,假设是最后一位是A,由于题目的要求是前缀 ,所以前面的放法数恰好是num[i-1][j-1][k]
另外两种情况同理,加的时候注意下标小于零就不要了
2一开始把所有的元素赋值为0,这样在三重for 中,根本没有将不满足ijk 不等关系的量作为左值。
3之所以可以这么算,是因为计算到i,j,k时需要的数据一定在之前算过了~
(这里只是把这个三维矩阵求了一个转置,不影响最后的结果num[n][n][[n])
import java.math.*; import java.util.*; import java.io.*; public class Main { public static void main(String[] args) throws Exception { BigInteger [][][] num=new BigInteger [65][65][65]; for(int i=0;i<65;i++) for(int j=0;j<65;j++) for(int k=0;k<65;k++) num[i][j][k]=BigInteger.ZERO; num[0][0][0]=BigInteger.ONE; for(int i=0;i<65;i++) for(int j=i;j<65;j++) for(int k=j;k<65;k++) { if(i>0)num[i][j][k]= num[i][j][k].add(num[i-1][j][k]); if(j>0)num[i][j][k]= num[i][j][k].add(num[i][j-1][k]); if(k>0)num[i][j][k]= num[i][j][k].add(num[i][j][k-1]); } Scanner cin=new Scanner(System.in); while(cin.hasNext()) { int n=cin.nextInt(); System.out.println(num[n][n][n]); System.out.println(); } } }
联想到括号匹配问题,长度为2n的字符串,有n个 “(” , 有n个“)” ,那么合法的式子(可以满足括号匹配)一共有多少? 答案就是 c(2n,n)-c(2n,n-1)=c(2n,n)/(n+1) =h(n)就是卡特兰数 ,也可以按照本题的思想来求 (当然要用高精度,下面写的到最后就溢出了)
#include<iostream> using namespace std; typedef long long inta; int main() { inta f[50][50]; for(int i=0;i<50;i++) for(int j=0;j<50;j++) f[i][j]=0; f[0][0]=1; for(int i=0;i<50;i++) for(int j=0;j<=i;j++) { if(i>0) f[i][j]+=f[i-1][j]; if(j>0) f[i][j]+=f[i][j-1]; } for(int i=0;i<50;i++) cout<<f[i][i]<<endl; }