半数集问题描述:
给定一个自然数n,由n 开始可以依次产生半数集set(n)中的数如下。
(1) n∈set(n);
(2) 在n 的左边加上一个自然数,但该自然数不能超过最近添加的数的一半;
(3) 按此规则进行处理,直到不能再添加自然数为止。
例如,set(6)={6,16,26,126,36,136}。半数集set(6)中有6 个元素。
半数集:多重集
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int a[1005];
int HalfSet(int n)
{
if(a[n] > 0)
return a[n];
else
{
a[n] = 1;
for(int i = 1;i <= n/2;i++)
a[n] += HalfSet(i);
return a[n];
}
}
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(a,0,sizeof(a));
printf("%d\n",HalfSet(n));
}
return 0;
}
半数单集:非单重集
半数单集类似半数集,区别在于:半数集是多重集,而半数单集不是多重集,即集合中已有的元素不再添加到集合中。
例如:n=24,那么半数集set(24)中的元素1224就有如下两种方式可以生成:
24 → 1224
24 →224 → 1224
所以,1224就是一个被重复计算的元素。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int a[1005];
int HalfSet(int n)
{
if(a[n] > 0)
return a[n];
else
{
a[n] = 1;
for(int i = 1;i <= n/2;i++)
{
a[n] += HalfSet(i);
if (i>10&&(i/10<=((i%10)/2)))
{
a[n] -= a[i/10];
}
}
return a[n];
}
}
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(a,0,sizeof(a));
printf("%d\n",HalfSet(n));
}
return 0;
}