整数除法矩阵之和

Posted

技术标签:

【中文标题】整数除法矩阵之和【英文标题】:Sum of integer Division matrix 【发布时间】:2016-12-12 05:39:21 【问题描述】:

这是之前 HackerEarth Challenge 的一个问题 -

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;

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

所以请告诉我我是否在这里正确地取得了成就。 如果是的话,我还能做些什么来优化这段代码。感谢您的帮助。

【问题讨论】:

不应该int temp = N*i/j;int temp = i/j; 即使你的答案是正确的,你的代码也有O(n^2) 的复杂性。对于这些在线法官网站来说,这几乎总是不合格的。 感谢@PaulMcKenzie 的建议。你能建议我如何减少/通过哪种方法来减少这个程序的复杂性。 @user216112,对于初学者,i/jj &gt; i 时为零。因此,内部循环可以是for (j = 1; j &lt;= i; ++j ) 进一步优化:有N-1i/j等于1。因此,您可以使用for ( j = 1; j &lt; i; ++j ) 并将N - 1 添加到答案中。 【参考方案1】:

请注意,int(i/j) 对于较大的 j 值变化不大

即如果j = 1000 int(i/j) 对于1-1000 将是0,那么对于1000-2000 它将是1,依此类推。使用这一事实,您可以创建复杂度低得多的算法。

例如如果N = 50000,那么对于j = 1000,你将得到0... (1000)times + 1 ..(1000)times + 2..(1000)times....直到49,000/1000... (1000)times。

div = N/jans += (div *(div-1) *j)

如果N/j 不是如下代码所示的整数,您还需要进行更正。

long long solve(long long N)
    long long ans = 0;
    long long div, mod;
    for (int i = 1; i <= N; i++)
    
        div = N/i;
        mod = i- N%i;
        ans += (div * (div+1) * i)/2;

        // For the case when N does not go directly into i,
        // e.g. N = 47500, i = 1000, the last 500 need to be removed from the sum
        ans -= (mod-1) * div;
        printf ("\n i = %d, ans = %lld",i,ans);
    
    return ans;

这是 O(n) 复杂度。

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

【讨论】:

通过去掉不必要的操作和嵌套循环,这看起来像是很好的优化 编译器不接受程序工作。根据系统如果输入为 2 2 4 预期正确输出应为 4 17 @user216112 基本思想是将矩阵展平为一维,并找到一个公式来计算总和。您知道样本数据是什么以及该站点声称的正确答案是什么。这个问题的设计是为了让你可以看到模式,而不是天真地写一个嵌套循环。 上述函数在提供输入 N=2 时导致 Sum =2 而不是 4。 @RishiKesh,你能帮我把这些 o(n^2) 问题破解成 0(n),我只需要知道你是如何解决这个问题的。如果有任何参考,请给我。我想详细研究一下。提前致谢。【参考方案2】:

第一列是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) 解决方案。

【讨论】:

谢谢,能不能提供一些通用方程来解决这个问题。【参考方案3】:

从复杂性的角度来看:

int x = int(i/j) 仅在 i &gt;= j 时表示 x &gt; 0。这样可以避免很多不必要的加法和除法。

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

因此,for 循环应该是:

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

更新 1:在 OP 使用示例输出更新问题后,ifor loop 似乎应该运行到 N。修改代码如下:

for(i = 1; i <= N; ++i)
    for(j = 1; j <= i; ++j)
        sum += (int)(i/j);

【讨论】:

我已经用一些示例输出编辑了这个问题,但我仍然无法达到所需的结果。请帮帮我。 @user216112:您是否修改了帖子中提到的代码。您的代码中有 2 个问题。 [1] for 循环应该直到 N 而不是直到 &lt; N-1。 [2] int temp = N*i/j; 应该是 int temp = i/j;【参考方案4】:

注意for-loop 条件

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 &lt; N-1;i++)(该选项会丢失最后一项)。

接下来,像i/j 这样带有整数的表达式是整数除法,它只有结果的整数部分(没有四舍五入)。如果i &lt; j,这将导致0 值。

最后一个,总结表达式应该是(来自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 &gt; 1000000时让你免于算术溢出

更新 2:

检查有关1 ≤ i, j ≤ N 的任务,如果真的是for as

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

【讨论】:

Matrix 从输入框中获取输入,在站点中他们可以选择这样做。 我找不到区别,ans += N * i / j is int temp = N*i/j; ans = ans + temp; 如果您需要尊重 - int temp = N*i/j; 需要更多 sizeof(int) 字节 谢谢,我也是这么想的,为了更清楚,我把拆分(想在 stackflow 中提问)设置为一样。 编译器不接受程序工作。根据系统如果输入为 2 2 4 预期正确输出应为 4 17

以上是关于整数除法矩阵之和的主要内容,如果未能解决你的问题,请参考以下文章

用Java如何求出一个整数的各位数字之和?

问题 C: 计算矩阵边缘元素之和

29.求3x3的整数矩阵对角线元素之和

CQOI2008矩阵的个数

有没有办法防止opencv矩阵除法中的舍入

矩阵各行元素之和