串的计数--动态规划和高精度

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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值