洛谷【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 }
我是这耀眼的瞬间,是划过天边的刹那火焰。
原文地址:https://www.cnblogs.com/Rane/p/9194488.html