整数除法矩阵之和
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/j
在j > i
时为零。因此,内部循环可以是for (j = 1; j <= i; ++j )
。
进一步优化:有N-1
次i/j
等于1
。因此,您可以使用for ( j = 1; j < 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/j
ans += (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 >= j
时表示 x > 0
。这样可以避免很多不必要的加法和除法。
即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 使用示例输出更新问题后,i
的 for loop
似乎应该运行到 N
。修改代码如下:
for(i = 1; i <= N; ++i)
for(j = 1; j <= i; ++j)
sum += (int)(i/j);
【讨论】:
我已经用一些示例输出编辑了这个问题,但我仍然无法达到所需的结果。请帮帮我。 @user216112:您是否修改了帖子中提到的代码。您的代码中有 2 个问题。 [1] for 循环应该直到N
而不是直到 < 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 < N-1;i++)
(该选项会丢失最后一项)。
接下来,像i/j
这样带有整数的表达式是整数除法,它只有结果的整数部分(没有四舍五入)。如果i < 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 > 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以上是关于整数除法矩阵之和的主要内容,如果未能解决你的问题,请参考以下文章