poj 2084 Game of Connections

探讨了2*n个圆周上点的连线问题,通过递推公式计算不同连接方式的数量,并提供了使用高精度计算的C++代码实现,此问题等价于计算卡特兰数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:2*n个点(一个圆周上的)连线,要求每个点必须与且仅与一个点相连,问有多少种方法。

思路:

对于2*n个点,任意选择其中一个点,这个点能和与它相距偶数个点的点相连,而相连的这条线会把整个图形分成两个子问题,即得到递推公式:

f[n] = f[0]*f[n-1] + f[1]*f[n-2] + f[2]*f[n-3] + ... + f[n-1]*f[0]。

注意高精度。

据说这是卡特兰数,详见百度百科,这个递推式很经典

#include <cstdio>
#include <cstring>
int n;
struct BigInt
{
	int data[60];
	BigInt& operator = (const BigInt &ob)
	{
		memcpy(data, ob.data, sizeof(data));
		return *this;
	}
	BigInt& operator += (const BigInt &ob)
	{
		if (data[0] < ob.data[0]) data[0] = ob.data[0];
		for (int i = 1; i <= data[0]; ++ i)
		{
			data[i] += ob.data[i];
			if (data[i] >= 10)
			{
				data[i] -= 10;
				data[i+1] ++;
			}
		}
		if (data[data[0]+1] != 0) data[0] ++;
		return *this;
	}
	void setDigit(int n)
	{
		memset(data, 0, sizeof(data));
		data[0] = 1;
		data[1] = n;
	}
	BigInt operator * (const BigInt &ob)
	{
		BigInt pro;
		pro.setDigit(0);
		pro.data[0] = data[0] + ob.data[0] - 1;
		for (int i = 1; i <= data[0]; ++ i)
			for (int j = 1; j <= ob.data[0]; ++ j)
				pro.data[i+j-1] += data[i] * ob.data[j];
		for (int i = 1; i <= pro.data[0]; ++ i)
		{
			pro.data[i+1] += pro.data[i] / 10;
			pro.data[i] %= 10;
		}
		while (pro.data[pro.data[0]] >= 10)
		{
			pro.data[pro.data[0]+1] += pro.data[pro.data[0]] / 10;
			pro.data[pro.data[0]] %= 10;
			pro.data[0] ++;
		}
		return pro;
	}
	void print()
	{
		for (int i = data[0]; i > 0; -- i)
			printf("%d", data[i]);
	}
} f[105];
void calc()
{
	f[0].setDigit(1);
	f[1].setDigit(1);
	for (int i = 2; i <= 100; ++ i)
	{
		f[i].setDigit(0);
		for (int j = 0; j < i; ++ j)
			f[i] += f[j] * f[i-j-1];
	}
}
int main()
{
	calc();
	while (scanf("%d",&n) && n!=-1)
	{
		f[n].print();
		printf("\n");
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值