整数除法矩阵之和

时间:2016-12-12 05:39:22

标签: c++ algorithm matrix

以下是HackerEarth挑战赛中的一个问题 -

Roy有一个大小为NxN的矩阵。行和列的编号从1到N. 第i行的第j列包含整数除法i / j。

换句话说,Matrix [i] [j] = int(i / j)其中1≤i,j≤N。

Your task is to find sum of this matrix i.e.

sum = 0
for i=1 to N-1
    for j=1 to N-1
        sum += Matrix[i][j]
Constraints:
1 ≤ T ≤ 10
1 ≤ N ≤ 1000000

这是我解决这个问题的方法

#include <cstdio>
#include <cassert>
using namespace std;
#define MAXT 10
#define MAXN 1000000
long long solve(long long N){
    long long ans = 0;
    for(int i=1;i<N-1;i++)
    {
    for(int j=1; j<N-1 ; j++)
    {
        int temp = N*i/j;
        ans = ans + temp;
    }
    }
    return ans;
}
int main(){
    int T, N;
    scanf("%d", &T);
    assert(T>0 and T<=MAXT);
    while(T--){
        scanf("%d", &N);
        assert(N>0 and N<=MAXN);
        printf("%lld\n", solve((long long)N));
    }
    return 0;
}

但是这个程序的输出结果不正确。

所以请告诉我,如果我在这里做得对。 如果是,我还可以做些什么来优化此代码。谢谢你的帮助。

enter image description here

4 个答案:

答案 0 :(得分:6)

请注意,对于int(i/j)

的较大值,j不会发生太大变化

即。如果j = 1000的{​​{1}} int(i/j)0,则1-10001,依此类推。使用这个事实,您可以创建一个复杂度更低的算法。

e.g。如果是1000-2000,那么对于N = 50000,您将获得j = 1000次+ 0... (1000)次+ 1 ..(1000)次......最多2..(1000)次。

即。 49,000/1000... (1000) div = N/j

如果ans += (div *(div-1) *j)不是整数,您还需要进行更正,如下面的代码所示。

N/j

这是O(n)的复杂性。

编辑:更正以修复预期结果。

答案 1 :(得分:1)

注意for - 循环条件

for i=1 to N-1  // in pseudo code

应该是

for(int i=1;i < N;i++)

for(int i=1;i <= N-1;i++)

但不是for(int i=1;i < N-1;i++)(该选项会丢失最后一项)。

接下来,像i/j这样的带整数的表达式是整数除法,它只有结果的整数部分(没有舍入)。如果0,则会产生i < j值。

最后一个,总结表达式应该是(从sum += Matrix[i][j]

ans += Matrix[i][j];

但你的矩阵在哪里?

<强>更新

如果出于同样的原因,您使用表达式N*i/j而不是矩阵(Matrix[i][j])中的值,并且您在防守上希望使用整数算术,则可以将代码最小化为:

long long solve(long long N){
    long long ans = 0;
    for (int i = 1; i < N; i++)
    {
        for (int j = 1; j < N; j++)
        {
            ans += N * i / j;
        }
    }
    return ans;
}

同时您应该了解long long

N > 1000000无法避免算术溢出

更新2:

检查有关1 ≤ i, j ≤ N的任务,如果确实是&lt; = N,请尝试将for更改为

   for (int i = 1; i <= N; i++)
    {
        for (int j = 1; j <= i; j++)
        {
             ans += i / j;
        }
    }

答案 2 :(得分:1)

从复杂性的角度来看:

int x = int(i/j)仅在x > 0时表示i >= j。因此,您可以避免许多不必要的添加和划分。

if Matrix[i][j] = int(i/j); then Matrix[i][j] = 0; for (i < j)

因此,for循环应为:

for i=1 to N-1
    for j=1 to i
        sum += Matrix[i][j];

更新1: OP上传了带有示例输出的问题后,for loop的{​​{1}}似乎应该运行到i。修改后的代码如下:

N

答案 3 :(得分:1)

第一栏是1, 2, 3, 4, 5, ... 第二列是0, 1, 1, 2, 2, 3, 3, 4, 4, ... 第三列是0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, ...

然后导出公式,使用算术级数和公式计算O(1)中列无循环的总和,并精确计算每列的开头和结尾。 然后迭代列。这将为您提供适合给定约束的O(n)解决方案。