【大数递推】HDU 1297——Children’s Queue

题目:点击打开链接

递推问题实现起来很简单,但得到递推公式确实很麻烦,就像DP一样。

分析(部分出自HDU的PPT):

设:F(n)表示n个人的合法队列,则:
按照最后一个人的性别分析,他要么是男,要么是女,所以可以分两大类讨论:
1、如果n个人的合法队列的最后一个人是男,则对前面n-1个人的队列没有任何限制,他只要站在最后即可,所以,这种情况一共有F(n-1);

2、如果n个人的合法队列的最后一个人是女,则要求队列的第n-1个人务必也是女生,这就是说,限定了最后两个人必须都是女生,这又可以分两种情况:
(1)、如果队列的前n-2个人是合法的队列,则显然后面再加两个女生,也一定是合法的,这种情况有F(n-2);

(2)难点在于,即使前面n-2个人不是合法的队列,加上两个女生也有可能是合法的,当然,这种长度为n-2的不合法队列,不合法的地方必须是尾巴,就是说,这里说的长度是n-2的不合法串的形式必须是“F(n-4)+男+女”,这种情况一共有F(n-4).


所以递推公式为F(n)=F(n-1)+F(n-2)+F(n-4).

另外需要注意的是 这个递推式的数据范围到了1000,int甚至long long 都已经无法承载最大边界,所以我使用了前两天贴出的大数类。

#include<iostream> 
#include<string> 
#include<iomanip> 
#include<algorithm> 
using namespace std; 

#define MAXN 9999
#define MAXSIZE 10
#define DLEN 4

class BigNum
{ 
private: 
	int a[500];    //可以控制大数的位数 
	int len;       //大数长度
public: 
	BigNum(){ len = 1;memset(a,0,sizeof(a)); }   //构造函数
	BigNum &operator=(const BigNum &);   //重载赋值运算符,大数之间进行赋值运算
	BigNum operator+(const BigNum &) const;   //重载加法运算符,两个大数之间的相加运算 
	void print();       //输出大数
}; 

BigNum & BigNum::operator=(const BigNum & n)   //重载赋值运算符,大数之间进行赋值运算
{
	int i;
	len = n.len;
	memset(a,0,sizeof(a)); 
	for(i = 0 ; i < len ; i++) 
		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(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;
}

BigNum que[1202];
//上边不是主要作用。。
int main()
{
	que[0]=1;
	que[1]=1;
	que[2]=2;
	que[3]=4;
	for(int i=4;i<=1000;i++)
	{
		que[i]=que[i-1]+que[i-2]+que[i-4];
	}
	int tar;
	while(cin>>tar)
	{
		que[tar].print();
	}
	return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值