时间限制(普通/Java)
:
1000 MS/ 3000 MS 运行内存限制 : 65536 KByte
总提交 : 143 测试通过 : 71
Accept: 1399 Submit: 4663
总提交 : 143 测试通过 : 71
比赛描述
给定一个自然数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)中的元素个数
(1) n∈set(n);
(2) 在n的左边加上一个自然数,但该自然数不能超过最近添加的数的一半;
(3) 按此规则进行处理,直到不能再添加自然数为止。
例如,set(6)={6,16,26,126,36,136}。半数集set(6)中有6 个元素,注意半数集是多重集。
对于给定的自然数n,编程计算半数集set(n)中的元素个数
输入
输入有多行,每行给出一个整数n。(0<n<1000)。
输出
对于输入的每一行,输出半数集set(n)中的元素个数。
样例输入
6
样例输出
6
思路:递归的模拟实现即可,注意开个数组优化一下,避免重复计算问题。
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long ll;
ll num[1005];
ll solve(int N){
if(num[N]>0)
return num[N];
ll ans = 1;
for(int i=1; i<=N/2; i++)
ans += solve(i);
num[N] = ans;
return ans;
}
int main(){
int N;
ll ans;
while(~scanf("%d",&N)){
ans = solve(N);
printf("%I64d\n",ans);
}
return 0;
}
Accept: 1399 Submit: 4663
Time Limit: 1000 mSec Memory Limit : 32768 KB
Problem Description
给定一个自然数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)中的元素个数。
Input
本题有多组输入数据,你必须处理到EOF为止。
每组数据只有1行,给出整数n。(0<n<201)
每组数据只有1行,给出整数n。(0<n<201)
Output
对于每组数据,输出只有1行,给出半数集set(n)中的元素个数。
Sample Input
6
Sample Output
6
思路:和上面的实现方式一样,就是一个去重的问题,加个判断条件即可。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long int ll;
ll num[205];
ll solve(int N){
if(num[N]>0)
return num[N];
ll ans = 1;
for(int i=1; i<=N/2; i++){
ans += solve(i);
if( i>10 && 2*(i/10)<=i )
ans -= solve(i/10);
}
num[N] = ans;
return ans;
}
int main(){
int N;
ll ans;
while(~scanf("%d",&N)){
ans = solve(N);
printf("%I64d\n",ans);
}
return 0;
}
推荐一篇博客: