【问题标题】:How to reduce the complexity of this code如何降低这段代码的复杂度
【发布时间】:2019-03-31 21:22:12
【问题描述】:
1<T<10 (where T is number of test cases)
1<N<1000

我们必须优化这段代码。

我尝试将小于N 的所有数字的因子从1 存储到N^2。但这仍然给了TLE

int count = 0;
for (int i = 1; i <= N; i++)
{
    for (int j = 1; j <= N; j++)
    {
        for (int k = 1; k <= N; k++)
        {
            if ((i * j) % k == 0)
             count++;
        }
    }
}
return count;

所以我猜它可能应该在 O(N^2) 中运行

【问题讨论】:

  • 是什么语言?请为其添加标签。
  • 你能试着在这里找到一个与手头的一般问题相匹配的标题吗?
  • 您可以通过按顺序写出调用使其成为 O(1): if ((1 * 1) % 1 == 0) count++;如果 ((2 * 1) % 1 == 0) 计数++; ...等
  • 这似乎是一个编程竞赛的问题。请提供原始问题陈述的链接,并确保它不是正在进行的比赛的一部分,因为这会被视为作弊。
  • 所以,乘法是对称的,i*j == j*i,它立即将时间减半。

标签: c++ optimization


【解决方案1】:

减少运行时间的一种简单方法是使用最大公约数(此处使用 c++17),如下所示:

#include <numeric>
int main(){
    int N = 1000;
    int count = 0;
    for (int k = 1; k <= N; ++k){
        for (int j = 1; j <= N; ++j){
            int gcd = std::gcd(j,k);
            count += N/(k/gcd);
        }
    }
    return count;
}

这有 O(N^2 log(N)) 的运行时间。 我相信通过分解 k 可以进一步降低复杂性,但解决方案可能会变得更加复杂。

编辑:可能有一个简单的数学公式可以在 O(1) 中解决这个问题。这需要一些思考。

【讨论】:

    【解决方案2】:

    离线编写代码并运行它。在文件中运行离线写入时。

    fprintf(f,"a[%d]=%d;",n,function(n));
    

    其中 a 是 1001 个元素的向量。 使用生成的代码。

    int function(int N) {
    int count = 0;
    for (int i = 1; i <= N; i++)
    {
        for (int j = 1; j <= N; j++)
        {
            for (int k = 1; k <= N; k++)
            {
                if ((i * j) % k == 0)
                 count++;
            }
        }
    }
    return count;
    }
    
    int main() {
    FILE* f = fopen("data.cpp","w");
    for(int i=1;i<=1000;++i) {
    fprintf(f,"a[%d]=%d;",n,function(n));
    if(i%10==0) fprintf(f,"\n");
    }
    fclose(f);
    return 0;
    }
    

    您在 PC 上运行此代码,在 data.cpp 中您将获得可用于实际解决方案的新部分源代码。

    int main() {
    int a[1001];
    // <- generated code here
    
    // here you will need to use a as a cached value instead of computing
    
    return 0;
    }
    

    【讨论】:

    • 你能否详细说明我无法理解:(
    • 这里的基本思想是数组查找是O(1)(例如,执行的代码可能是return lookupTable[n];),因为N很小,所以查找表的成本会很小(例如 4000 字节 - 不够关心)。如果您将代码转换为生成查找表源代码的实用程序,您只需运行该实用程序一次,那么您可以在程序中包含查找表,您的程序将是 O(1)。跨度>
    • 我认为这个答案很愚蠢。维克多,你知道这不是 OP 想要的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多