• (数论)数的计算


    题目描述 Description

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

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

    1.          不作任何处理;

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

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

    输入描述 Input Description

    一个数n

    输出描述 Output Description

    满足条件的数的个数

    样例输入 Sample Input

    6

    样例输出 Sample Output

    6

    数据范围及提示 Data Size & Hint

    6个数分别是:

    6

    16

    26

    126

    36

    136

    分析:

        1. 本题难度看似不大,但如果用递归来做的话耗时非常大,因为需要重复计算的数据量太大了。当然我们也可以采取一边递归一边储存的方法,但计算量也还是不小,再进一步思考,实际上就是可以用如下的递推法来做;
        2. 例如要求f(6),经过分析,我们知道:f(6)=f(1)+f(2)+f(3)+1,也就是说,f(6)的答案数量是在它之前可以取的所有自然数的答案数量之和(6之前可以取1,2,3三个自然数),最后加1是指数字6本身也是一个答案;
        3. 所以,我们可以知道f(n)=f(1)+f(2)+......f(trunc(n/2))+1;
        4. 因此,要求f(n),我们只需用上述公式编一个递推过程,把f(2)到f(n)全部求出即可,对于f(1000)也不超过1秒就能得到结果。
        第二种算法:
        1. 对于f(7)=f(6)是显而易见的,也即f(2n+1)=f(2n)。那么,f(8)和f(7)之间有什么关系呢?
        2. 分析可知:f(8)和f(7)的差别是,f(8)除了包含f(7)的所有情况外,还要多加上f(4),即:f(8)=f(7)+f(4)。因此可得:f(2n)=f(2n-1)+f(n)。只需据此编一个递归小过程或者用递推方法即可。

     1 #include <iostream>
     2 using namespace std;
     3 int main()
     4 {
     5     int i,n,ans,sum[1001];
     6     sum[0] = 0,sum [1] = 1;
     7     cin>>n;
     8     for(i = 2 ; i <= n ; i++)
     9     {
    10         ans = sum[i/2] + 1;
    11         sum [i] = sum[i-1] + ans;
    12     }
    13     cout<<sum[n] - sum[n-1]<<endl;
    14     return 0;
    15 }
    View Code
    随便写写。一点学习心得。。。--如果本文章没有注明转载则为原创文章,可以随意复制发表,但请注明出处与作者
  • 相关阅读:
    OpenCV中threshold函数的使用
    opencv中namedWindow( )函数
    Open CV leaning
    RGB颜色表
    visual studio 2015 Opencv4.0.1配置
    uint16_t
    Arduino重置-复位问题
    bzoj1823 [JSOI2010]满汉全席(2-SAT)
    bzoj2208 [Jsoi2010]连通数(scc+bitset)
    UVAlive3713 Astronauts(2-SAT)
  • 原文地址:https://www.cnblogs.com/ganhang-acm/p/4167513.html
Copyright © 2020-2023  润新知