【洛谷P1028】数的计算(递归、DP)

本文探讨了一个有趣的数学问题,通过递归和动态规划的方法,计算一个数字左侧可放置1到其一半之间的任意整数,形成的所有可能数字组合数量。提供了两种算法实现,包括递归和更高效的动态规划方法。

题目链接
此题要求:
给出一个数字n,可以在这个数字左面放上1~n/2间任意一个整数,
放上数后,可以继续在左边放数,这个数同样要满足1~n/2间任意一个整数。当然,也可以不放。(n<=1000)
最终要求输出,按照这样的规则,一共能构成多少个数字。
例如:输入6,那么满足这样规则的数字有6 16 26 36 126 136
这个题目给出的例子告诉我们,本题不把0当做自然数
下面开始解析:
根据题目描述的要求,我们很容易想到一个思路,就是递归,这样做由于递归过多,会TLE。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll fun(ll n)
{
	ll sum=n/2;
	if(n==1)
	return sum;
	for(int i=1;i<=n/2;i++)
	{
		sum+=fun(i);
	}
	return sum;
}
int main()
{
	int n;
	cin>>n;
	if(n==0||n==1)
	cout<<1<<endl;
	else
	cout<<fun(n)+1<<endl;
	return 0;
}

那怎么做呢?
让我们试想输入为1~6的情况

输入输出
11
22
33
44
54
66

如果输入为6的话,那么它左边的数字有1、2、3 ,而1、2、3又要继续按照这样的规则进行,此时我们已经知道了输入为1、2、3时的输出,可以发现n所构成的符合规则的数=1(n这个数本身)+∑(1~n/2)构成符合规则的数之和。
由于前几个数字我们已经知道了,下面递推后面的数字进行打表即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;		//实际上第1000个数只有19亿多 没爆int
int main()
{
	int n;
	int a[1010]={1,1,2,2,4,4,6};
	scanf("%d",&n);
	for(int i=7;i<=1000;i++)
	{
		int sum=1;
		for(int j=1;j<=i/2;j++)
			sum+=a[j];
		a[i]=sum;
	}
	printf("%d",a[n]);
	return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

农民真快落

我琢磨着也没人给我打赏呀。。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值