半数集问题

问题描述:
给定一个自然数n,由n 开始可以依次产生半数集set(n)中的数如下。
(1) n∈set(n);
(2) 在n 的左边加上一个自然数,但该自然数不能超过最近添加的数的一半;
(3) 按此规则进行处理,直到不能再添加自然数为止。
例如,set(6)={6,16,26,126,36,136}。半数集set(6)中有6 个元素。
注意半数集是多重集。
对于给定的自然数n,计算半数集set(n)中的元素个数。

 

半数集set(n)中元素个数的求解是个递归的过程。设set(n)中的元素个数为f(n),则显然有递归表达式:

f(n)=1+∑f(i),i=1,2……n/2

	// 递归算法
	long comp(int n)
	{
		long sum = 1; // 记录半数集中产生的元素个数
		if (n <= 1)
			return 1;
		for (int i=1; i<=n/2; i++)
		{
			sum += comp(i);
		}
		return sum;
	}
	// 非递归实现
	int n = 12;  
	int[] s = new int[n+1];
	int comp(int n, int[] s)
	{
		int sum = 1;
		
		// 已经计算过
		if (s[n] > 0)
			return s[n];
		
		for (int i=1; i<=n/2; i++)
		{
			sum += comp(i);
		}
		
		s[n] = sum; // 数n的半数集元素个数
		
		return sum;
	}

 半数单集问题:

半数单集类似半数集,区别在于:半数集是多重集,而半数单集不是多重集,即集合中已有的元素不再添加

到集合中。例如 24。 24->1224 ,  24->224->1224。

对于n<=200的情况。在0 < n < 201时,0 < n/2 <= 100,在计算时,可能产生重复的元素是2位数。一个两位数

x重复产生的条件是:其个位数y = x % 10的半数集中已经产生了x(个位数是十位数的至少两倍), 因此

x /10 <= y / 2,或 2(x / 10) <= x % 10。

 

	// 非递归实现
	int n = 2; // 2448  1248    
	int[] s = new int[n+1];
	int comp(int n, int[] s)
	{
		int sum = 1;
		
		// 已经计算过
		if (s[n] > 0)
			return s[n];
		
		for (int i=1; i<=n/2; i++)
		{
			sum += comp(i);
			if (i > 10 && (2*(i/10)<=(i%10)))
				sum -= s[i/10];
		}
		
		s[n] = sum; // 数n的半数集元素个数
		
		return sum;
	}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值