【问题标题】:sum's sum of divizors of numbers less than or equal to Nsum 小于或等于 N 的数的除数之和
【发布时间】:2015-10-24 01:39:41
【问题描述】:

我真的需要一些帮助来解决这个问题:

给定一个正整数N,我们将xsum(N)定义为所有小于或等于N的正整数除数之和。

例如:xsum(6) = 1 + (1 + 2) + (1 + 3) + (1 + 2 + 4) + (1 + 5) + (1 + 2 + 3 + 6) = 33 .
(xsum - 1 的除数总和 + 2 的除数总和 + ... + 6 的除数总和)

给定一个正整数K,要求您找到满足条件的最小Nxsum(N) >= K

K 是一个非零自然数,最多有 14 位数字

时间限制:0.2 秒

显然,在超过时间限制的大多数情况下,蛮力将下降。我还没有找到比它更好的东西,所以这就是代码:

fscanf(fi,"%lld",&k);
i=2;
sum=1;
while(sum<k) {
    sum=sum+i+1;
    d=2;
    while(d*d<=i) {
          if(i%d==0 && d*d!=i)
             sum=sum+d+i/d;
          else
             if(d*d==i)
                 sum+=d;
           d++;
    }
    i++;
}

有更好的想法吗?

【问题讨论】:

  • 14位表示14位?还是十进制数字?反正。这个问题是题外话。 SO 不是 code-rview 站点。如果您的代码有效,请尝试code review。但首先阅读他们的常见问题解答(您显然没有阅读 SO)!
  • 14 位十进制数字。我的代码有效,我之所以写它是因为我阅读了您必须展示您的工作、您尝试做什么等规则。

标签: c algorithm optimization


【解决方案1】:

对于 [1 , N] 范围内的每个数字 n,以下适用:n 是 [1 , N] 范围内的 roundDown(N / n) 数字的除数。因此,对于每个n,我们将总计n * roundDown(N / n) 添加到结果中。

int xsum(int N){
    int result = 0;

    for(int i = 1 ; i <= N ; i++)
        result += (N / i) * i;//due to the int-division the two i don't cancel out

    return result;
}

该算法背后的思想也可用于以比蛮力搜索更快的速度解决主要问题 (smallest N such that xsum(N) &gt;= K)。

使用我们可以从上面的代码中得出的一些规则可以进一步优化完整的搜索:K = minN * minN(如果K = 2 * 3 * ...)minN 将是正确的结果。使用此信息,我们有一个开始搜索的下限搜索。

下一步是搜索上限。由于xsum(N) 的增长(近似)是二次的,我们可以用它来近似N。这种优化的猜测可以很快找到搜索到的值。

int N(int K){
    //start with the minimum-bound of N
    int upperN = (int) sqrt(K);
    int lowerN = upperN;

    int tmpSum;
    //search until xsum(upperN) reaches K
    while((tmpSum = xsum(upperN)) < K){
        int r = K - tmpSum;

        lowerN = upperN;
        upperN += (int) sqrt(r / 3) + 1;
    }

    //Now the we have an upper and a lower bound for searching N
    //the rest of the search can be done using binary-search (i won't
    //implement it here)

    int N;//search for the value

    return N;
}

【讨论】:

  • 谢谢,我不得不承认我没有听说过阿特金筛。在尝试理解此解决方案之前,我必须记录下来。
  • @scummy 如果性能不是那么重要,您也可以简单地使用 Erathostenes 筛
  • 这就是我要做的
  • 等一下,我刚刚考虑了整个事情,实际上有一个更简单的解决方案来解决这个问题。我会编辑
  • @scummy 我用更简单的(线性)解决方案更新了答案
猜你喜欢
  • 1970-01-01
  • 2020-12-18
  • 1970-01-01
  • 2019-09-25
  • 1970-01-01
  • 2021-06-09
  • 2021-11-04
  • 2020-01-01
  • 2021-11-12
相关资源
最近更新 更多