【问题标题】:Find the sum of digits of a sequence of integers查找整数序列的数字总和
【发布时间】:2014-11-08 06:27:34
【问题描述】:

我决定编写一小段代码来获取两个整数,假设 M 和 N ( M

#include <iostream>
#include <vector>

using namespace std;
// the partial digits sums digitSum[i] = the sum of the digits between 0 and i
int digitSum[] = {0, 1, 3, 6, 10, 15, 21, 28, 36, 45};
int pow_of_ten[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
 // the sums of all the digits in the numbers from 1 to (10^(i) - 1) where i is the index in the array
long subsums[] = {0, 45, 20 * 45, 300 * 45, 4000 * 45, 50000 * 45, 600000 * 45, 7000000 * 45, 80000000 * 45,
    900000000 * 45};
//Calculates the sum of all digits between 0 and M inclusive
long Digit_Sum(int M) {

  if (M < 10) {
    return digitSum[M];
  }
  long result = 0;
  int same = M;
  int counter = 0;
  int lastdigit = 0;
  while (same > 0) {
    if (same <  10) {
      lastdigit = same;
      break;
    }
    same /= 10;
    counter ++;
  }
  for(;counter >= 0; counter --) {
    result += (subsums[counter] + M % pow_of_ten[counter] + 1) * lastdigit;
    result += digitSum[lastdigit - 1] * pow_of_ten[counter];
    if (counter == 0) {
      break;
    }
    lastdigit = (M / pow_of_ten[counter - 1]) % 10;
  }
  return result;

}

int main() {

int M;
int N;
vector<long> sums;
while (true) {
  cin >> M >> N;
  if (M == 0 &&  N == 0) {
    break;
  }
  sums.push_back(Digit_Sum(N) - Digit_Sum(M - 1));
}

for (vector<long>::iterator it = sums.begin(); it != sums.end(); ++it) {
  cout << *it << endl;
}
}

在大多数情况下,这很有效,但在线法官说这是错误的。我查看了其他可行的解决方案,但没有人像我那样对数组中的值进行硬编码。这可能会导致部分问题,有什么想法吗?

【问题讨论】:

  • 你可以用一行循环来执行这个逻辑,为什么所有增加的复杂性?
  • 你可以用一个一个简单的表达式来执行这个逻辑,只需计算它。提示:如果您考虑计算两次总和,则可以将其视为一个值序列加上反向序列的总和。
  • 简单公式M*(M+1)/2是不是不能用?
  • @RSahu Sahu 如何使用此表格计算序列的位数
  • 我的意思是,到目前为止,显然您已经对两位回答者中的任何一个问题进行了更多思考,并找到了他们甚至没有想过要寻找的模式。但是您需要与我们分享这种想法,以便我们进行故障排除。期望我们从代码中对设计进行逆向工程是疯狂的,而从头开始设计解决方案也是一项过多的工作。

标签: c++ vector iterator sum digits


【解决方案1】:

您可以轻松地创建一个 for 循环来大大简化此代码。

没有必要费尽心思。

for (Initialization Action, Boolean Expression, Update_Action)

【讨论】:

  • 使用 for 循环可以转换哪个部分并且既简单又快速。这里涉及什么样的错误,我看不到。是的,我可以删除递归并进行循环,这是您的意思吗?
  • 我没有看到任何错误,我只是说您可以使用 for 循环大大简化此代码。
【解决方案2】:

下面重新删除:对不起,我有点感冒,把N读成M。 :(

我认为主要错误是M-1 in

       sums.push_back(Digit_Sum(N) - Digit_Sum(M - 1));

还要注意修正后该公式仅适用于一位数。鉴于该公式和您的示例,我之前关于使用简单公式的评论是基于对您的问题描述的误解。两者都只表示一位数字。

但是,代码的复杂性似乎高得离谱。考虑一下,假设非负整数作为输入,并假设m 始终小于或等于n

#include <iostream>
#include <stdexcept>
using namespace std;

bool throwX() { throw std::runtime_error( "Ouch." ); }

auto main() -> int
{
    for( ;; )
    {
        int m, n;
        cin >> m >> n || throwX();
        if( m == 0 && n == 0 ) { break; }

        int sum = 0;
        for( int i = m; i <= n; ++i )
        {
            for( int v = i; v != 0; v /= 10 )
            {
                sum += v % 10;
            }
        }
        cout << sum << endl;
    }
}

不需要比这更复杂。

【讨论】:

  • 除非您想要比O((N-M) lg N) 更好的复杂性,在这种情况下将需要更智能的方法。
  • @BenVoigt:是的。并且差异公式可能适用于更智能的方法,但是 Digit_sum 的命名有点误导(它必须计算所有数字的数字总和,包括参数)。代码仍然没有那么复杂。
  • 对不起,我有点流感,把N误读为M。 :( 修复。
  • 是的@Cheersandhth.-Alf 这种方法效果很好,尽管它不符合 1 秒的时间限制。
  • @Cheersandhth.-Alf,你能详细说明一下内部两个嵌套的 forloops 吗?
【解决方案3】:

经过测试并符合规范,无控制台输入:

#include <iostream>
#include <string>
using namespace std;

void sum_a_to_b(const int & a, const int & b)
{
    if (a <= b && a >= 0)
    {
        long long sum = 0;
        for (int i = a; i <= b; i++)
        {
            sum += i;
        }
        cout << "Sum of digits from " << a << " through " << b << " is " << sum << ".\n";
    }
}

int main()
{
    sum_a_to_b(5, 6);
    sum_a_to_b(1, 9);
}

【讨论】:

  • 这会计算数字的总和,而不是它们(十进制表示)数字的总和。
  • 我们正在求序列中所有数字的小数位数之和。将更改顶部的示例。
猜你喜欢
  • 1970-01-01
  • 2013-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多