P1028 数的计算

P1028

题目描述

我们要求找出具有下列性质数的个数(包含输入的自然数n):

先输入一个自然数n(n1000),然后对此自然数按照如下方法进行处理:

  1. 不作任何处理;

  2. 在它的左边加上一个自然数,但该自然数不能超过原数的一半;

  3. 加上数后,继续按此规则进行处理,直到不能再加自然数为止.

输入输出格式

输入格式:

  1个自然数n(n1000)

输出格式:

  1个整数,表示具有该性质数的个数。

 

输入输出样例

输入:

6

输出:

6

 

 

分析:

  这道题理论上是可以用暴力递归的,但是会超时。

  也可以写递推公式:

  首先,f[n]表示输出符合的个数。

  n=0、n=1时,f[n]=1

  n=2,f[n]=2  n=3,f[n]=2

  n=4,f[n]=4  n=5,f[n]=4

  n=6,f[n]=6  n=7,f[n]=6

  可以看出,2n与2n+1(n为非负整数)的答案是一样的。

  以8为例,

    8

    18  28    38   48

                128     138    148  248

                      1248

  排序树??

  ①当我们把8和8下面的左三棵子树放在一起,并将所有的8都改成7,我们能发现,我们得到了n=7时的所有解。//n-1

     7

         17   27    37  

                  127   137   

 

  我们再把最右端的子树(即剩下的部分)中的所有8删去,我们得到了n=4时的所有解。//n/2

       4

              14   24

          124

  取n时,类比上例。

  于是,可以得到: f[i]=f[i-1]+f[i/2]。

  我们又知道2n与2n+1(n为非负整数)的答案是一样的。

  所以,n为偶数时,直接用递推公式,n为奇数时,把它换成对应的偶数再套递推公式。

 

代码:

 

 1 #include <bits/stdc++.h>  //注意是斜杠而不是反斜杠 
 2 using namespace std;
 3 int main(){
 4     int n,f[1000];
 5     f[0]=f[1]=1;
 6     cin>>n;
 7     for(int i=2;i<=n;i++){
 8       if(i%2==0)f[i]=f[i-1]+f[i/2];
 9       else f[i]=f[i-1];
10     }
11     printf("%d",f[n]);
12     return 0; 
13 }

 

posted @ 2019-02-17 12:47  cruelty_angel  阅读(195)  评论(0编辑  收藏  举报