http://www.rqnoj.cn/Problem_38.html
题目:串的记数
问题编号:38
题目描述
一个长度为3N字符串满足:由N个A,N个B,N个C组成,对于它的任意前缀,满足A的个数>=B的个数>=C的个数。求满足这样条件的字符串的个数。
数据范围:
10%的数据满足0<=n<=5
100%的数据满足0<=n<=60
输入格式
输入文件只有一行,为1个整数N(0<=n<=60)。
输出格式
所求的答案
样例输入
4
样例输出
462
一、思路
每个字串以A或B或C结束 那么定义f[a][b][c],来表示当有a个A,b个B,c个C时的满足题意的字符串个数
f[a][b][c] = f[a-1][b][c]+f[a][b-1][c]+f[a][b][c-1] 即以A结束有f[a-1][b][c]个 B结束有f[a][b-1][c] C结束有f[a][b][c-1]个 三者的总和
初始条件为f[0][0][0] = 1 且 a>=b>=c 否则为0
因为数据量70多位 所以用到了高精度加法
f[a][b][c][20] 来存储,其中第四维来表示个数,用20个整型数来表示 8*20= 160 位数 足够了对本题
1、读入n
2、三重循环,动态规划,高精度加法求和
3、输出结果
1)找到最高位
2)补0输出非最高位
二、代码如下
#include <iostream.h>
#include <fstream.h>
#define NUM 10000000
int f[61][61][61][20];
int main()
{
int n;
int a, b, c, p;
int i, j;
//读入n
cin>>n;
f[0][0][0][0] = 1;
for (a=0; a<=n; a++)
{
for (b=0; b<=a; b++)
{
for (c=0; c<=b; c++)
{
//高精度 1 000 000
for (p=0; p<20; p++)
{
f[a][b][c][p] += a>0?f[a-1][b][c][p]:0;//防止越界
f[a][b][c][p] += b>0?f[a][b-1][c][p]:0;
f[a][b][c][p] += c>0?f[a][b][c-1][p]:0;
if (!f[a][b][c][p])
{
break;
}
if (f[a][b][c][p]>=NUM)
{
f[a][b][c][p+1] += f[a][b][c][p]/NUM;
f[a][b][c][p] %= NUM;
}
}
}
}
}
//输出,找最高位置
p=19;
while (!f[n][n][n][p])
{
p--;
}
p = p<0?0:p;
//输出最高位
cout<<f[n][n][n][p];
//补0输出
for (p=p-1; p>=0; p--)
{
//判断位数
int bit = 10;
for (i=1; i<=7; i++)
{
if (f[n][n][n][p]/bit==0)
{
break;
}
bit *= 10;
}
//输出0
for (j=1; j<=7-i; j++)
{
cout<<0;
}
cout<<f[n][n][n][p];
}
return 0;
}