半数单集问题(set.cpp)

【问题描述】
给定一个自然数 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
",ans);
  return 0;
}
原文地址:https://www.cnblogs.com/gshdyjz/p/9870874.html