【问题描述】
给定一个自然数 n,由 n 开始可以依次产生半数集 set(n)中的数如下。n∈set(n);在 n 的
左边加上一个自然数,但该自然数不能超过最近添加的数的一半;按此规则进行处理,直到
不能再添加自然数为止。
例如,set(6)={6,16,26,126,36,136}。半数集 set(6)中有 6 个元素。
注意半数集不是多重集。集合中已经有的元素不再添加到集合中。
对于给定的自然数 n,编程计算半数集 set(n)中的元素个数。
【输入】
输入文件只有 1 行,给出整数 n。
【输出】
输出文件只有 1 行,给出半数集 set(n)中的元素个数。
【样例】
输入文件示例
set.in
6
【数据范围】
30%数据:1<=n<=20
100%数据:1<=n<=200
输出文件示例
set.out
6
这题很显然可以用递归来计数,但是我们会发现其实在递归过程中可能会重复,那么什么情况下才会重复呢?
当当前自然数/2后等于另外一个自然数/2和之后的,比如1224就可能由12<-24和1<-2<-24组成。
但是这种情况只在当前自然数大于10并且它的个位数大于等于它的十位数×2。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define il inline
#define ll long long
#define db double
using namespace std;
int ans=0;
il int count(int x)
{
int s=0;
if(!x)
return 1;
for(int i=0;i<=x/2;i++)
{
s+=count(i);
if(i>10&&(2*(i/10))<=i%10)
s-=count(i/10);
}
return s;
}
int main()
{
freopen("set.in","r",stdin);
freopen("set.out","w",stdout);
int n;
cin>>n;
ans=count(n);
printf("%d\n",ans);
return 0;
}