问题 A: 复杂度分析(Ⅰ)

问题 A: 复杂度分析(Ⅰ)

时间限制: 1 Sec 内存限制: 128 MB

题目描述
分析如下代码

for(i=1;i<n;i++)
  for(j=1;j<i;j++)
    for(k=1;k<j;k++)
      printf("\n");

问printf语句共执行了几次?这段代码执行完以后i+j+k值为多少?

输入
由多行组成,每行一个整数n, 1<= n <= 3000

输出
对每一行输入,输出对应的一行,包括空格分开的两个整数,分别代表printf语句的执行次数以及代码执行完以后i+j+k的值, 如果值不确定,输出"RANDOM"取代值的位置

样例输入
6
样例输出
10 15

计算过程

1.运算中,发现若仅使用整形变量,会导致计算结果出现问题:
1.1情况一:数据超出整型变量计算范围导致空间超限
1.2情况二:整型变量数据范围小导致计算所用时间过长运算超时,所以需要使用超长整型变量扩大运算范围,节省运行时间

2.1当n小于或等于3时及时n运行为2,最后一句执行printf所相连的for循环不满足条件无法进入,所以执行次数为0,循环次数为1+2+3=6
2.2当n大于3时若使用题干所给代码时间复杂度为O(n3),此时运算结果显示超时,所以需要通过数学方法计算将时间复杂度简化,通过循环次数的计算,可将题干所给三层循环简化为一层循环的数学计算式

这段代码是一个三层嵌套循环,其逻辑是打印出换行符。下面是如何计算 printf 语句执行次数、i+j+k 值的总和以及代码的运行逻辑:

  1. 计算 printf 执行次数

    • 外层循环 i 从 1 迭代到 n-1(因为 i < n)。
    • 中层循环 j 从 1 迭代到 i-1(因为 j < i)。
    • 内层循环 k 从 1 迭代到 j-1(因为 k < j)。
    • 对于每一个 ij 的取值范围是从 1 到 i-1,而 k 的取值范围是从 1 到 j-1
    • 因此,printf 执行次数的总和是所有可能的 (i, j, k) 组合的数量。
  2. 计算 i+j+k 值的总和

    • 要计算 i+j+k 的总和,可以分别计算 ijk 的总和,然后相加。
  3. 运行逻辑

    • 对于每一层循环,ijk 都是逐步增加的,但每一层的增加都是基于内层循环的完成。
    • k 达到它的上限(j-1)时,k 重置为 1,j 增加 1。
    • j 达到它的上限(i-1)时,j 重置为 1,i 增加 1。

下面是具体的计算方法:

  • i 的总和是等差数列求和:(1 + 2 + ... + (n-1))
  • 对于每一个 ij 的总和是:(1 + 2 + ... + (i-1))
  • 对于每一个 (i, j) 对,k 的总和是:(1 + 2 + ... + (j-1))

printf 执行次数的总和可以用下面的公式计算:
[ \text{总次数} = \sum_{i=1}^{n-1} \sum_{j=1}^{i-1} \sum_{k=1}^{j-1} 1 ]

i+j+k 值的总和可以用下面的公式计算:
[ \text{总和} = \sum_{i=1}^{n-1} i \left( \sum_{j=1}^{i-1} j \left( \sum_{k=1}^{j-1} k \right) \right) ]

由于这是一个立方求和问题,计算起来相对复杂,通常需要使用数学工具或编程方法来求解。

注意:上述公式中的求和项是连续整数的和,可以使用等差数列求和公式简化计算。对于 ijk 的总和,可以使用以下公式:
[ \text{某个变量的总和} = \frac{n(n + 1)(2n + 1)}{6} - \frac{n^3}{2} ]
其中 n 是该变量在最外层循环中的上限减 1。对于 k,上限是 j-1,所以 n 应该是 i-1j-1。这个公式是连续整数和的求和公式,但需要适当调整以适应嵌套循环的边界条件。

AC代码

部分实现

代码如下(n<=3):

   if( n <= 3)
    {
        if( n < 3 )
        printf("0 RANDOM\n");
        else printf("0 6\n");
    }

代码如下(n>3):

else
    {
        sum = 3*n - 3;
        for( i = 3,k = 1; i < n ; i++,k++)
        {
            a = k + a;
            t = t + a;
        }
        printf("%lld %lld\n",t,sum);
    }
}

AC代码

代码如下:

#include<bits/stdc++.h>
using namespace std;
int main()
{
//运算中,发现若仅使用整形变量,会导致计算结果出现问题,情况一:数据超出整型变量计算范围导致空间超限,情况二:整型变量数据范围小导致计算所用时间过长运算超时,所以需要使用超长整型变量扩大运算范围,节省运行时间
    int n;
    while( scanf("%d",&n)!= EOF )
{
    long long t=0,sum,i,k,a=0;
//当n小于或等于3时及时n运行为2,最后一句执行printf所相连的for循环不满足条件无法进入,所以执行次数为0,循环次数为1+2+3=6
    if( n <= 3)
    {
        if( n < 3 )
        printf("0 RANDOM\n");
        else printf("0 6\n");
    }
else
//当n大于3时若使用题干所给代码时间复杂度为O(n3),此时运算结果显示超时,所以需要通过数学方法计算将时间复杂度简化,通过循环次数的计算,可将题干所给三层循环简化为一层循环的数学计算式
    {
        sum = 3*n - 3;
        for( i = 3,k = 1; i < n ; i++,k++)
        {
            a = k + a;
            t = t + a;
        }
        printf("%lld %lld\n",t,sum);
    }
}
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值