sum的小于或等于N的数字的除数之和

时间:2015-08-01 12:50:52

标签: c algorithm optimization

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

  

给定正整数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++;
}

有更好的想法吗?

1 个答案:

答案 0 :(得分:0)

对于范围[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) >= K)比蛮力搜索更快的时间。

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

下一步是搜索上限。由于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;
}