zoukankan      html  css  js  c++  java
  • 洛谷【P1028】数的计算

    这一题被放在了递归与递推的标签下,但是通过n<=1000的数据量不难推算出如果使用递归,时间复杂度会呈指数级增长。

    故个人拙见:使用记忆化搜索是此题的最优解。

    先看一组代码。

     1 #include <iostream>
     2 #include <cstdio>
     3 using namespace std;
     4 int n, s[1005];
     5 int main(){
     6     cin>>n;
     7     for(int q=1; q<=n; q++){
     8         s[q]++;
     9         for(int z=1; z<=q/2; z++){
    10             s[q] += s[z];
    11         }
    12     }
    13     cout<<s[n];
    14     return 0;
    15 }

    在读完题后可先进行手动模拟。以6为例,存在

      ①  6

      ②  16

      ③  26  126

      ④  36  136

    可以看出,当 n 为 6 时,s[6] = s[1]+s[2]+s[3]+1。

    故从s[1]开始记忆,到 s[n]停止。

     

    But,用ans来表示具有改性质数的个数,手动模拟时,我们会得到一组简单的数据。

    n=0,ans=1;  n=1,ans=1;

    n=2,ans=2;  n=3,ans=2;

    n=4,ans=4;  n=5,ans=4;

    n=6,ans=6;  n=7,ans=6;

    会发现,① n为奇数时,s[n]=s[n-1],

        ② n为偶数时,s[n]=s[n-1]+s[n/2]。

        ③ s[0]=s[1]=1;

    那么便可以使用一层循环来解决问题,代码如下:

     1 #include <iostream>
     2 #include <cstdio>
     3 using namespace std;
     4 int n,s[1005];
     5 int main(){
     6     s[1]=1;
     7     cin>>n;
     8     for(int q=2; q<=n; q++){
     9         if(q%2 == 0){
    10             s[q] = s[q-1] + s[q/2];
    11         }else{
    12             s[q] = s[q-1];
    13         }
    14     }
    15     cout<<s[n];
    16     return 0;
    17 }
    我是这耀眼的瞬间,是划过天边的刹那火焰。
  • 相关阅读:
    poj 2378 删点最大分支不超过一半
    poj 3107 删点最大分支最小
    hdu 3586 最小代价切断根与叶子联系
    hdu 4276 树形m时间1进n出
    hdu 4044 树形DP 炮台打怪 (好题)
    poj 3345 树形DP 附属关系+输入输出(好题)
    poj 2486 树形DP n选m连续路径
    hdu 1561 树形DP n个选m个价值最大
    poj 1947 树形背包
    hdu 1011 树形背包
  • 原文地址:https://www.cnblogs.com/Rane/p/9194488.html
Copyright © 2011-2022 走看看