半数单集问题(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\n",ans); return 0; }
PEACE