题目链接
此题要求:
给出一个数字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的情况
| 输入 | 输出 |
|---|---|
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 4 |
| 6 | 6 |
如果输入为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;
}
本文探讨了一个有趣的数学问题,通过递归和动态规划的方法,计算一个数字左侧可放置1到其一半之间的任意整数,形成的所有可能数字组合数量。提供了两种算法实现,包括递归和更高效的动态规划方法。
748

被折叠的 条评论
为什么被折叠?



