Problem statement: We have given a number N and we have to find out the sum of digits in all numbers from 1 to N.
问题陈述:我们给了一个数字N ,我们必须找出从1到N的所有数字的数字总和 。
Solution
解
Brute force approach:
蛮力法:
Simple idea for solution is that if we get number greater than 9, i.e., the number having more than one digit, we extract every individual digit of that and sum together to find final result.
解决方案的简单想法是,如果我们得到大于9的数字,即数字多于一个数字,我们将提取该数字的每个数字并将其求和以得出最终结果。
function sum(N) //brute force approach
sum = 0;
for(i =1 to N)
{
temp = i;
while(temp != 0)
{
sum = sum + temp%10;
temp = temp/10;
}
}
return sum;
END FUNCTION
The time complexity for this solution in O(Nlog10(N)) as we have to sum N items and in worst case the number of digits a number has is log10(N).
O(Nlog10(N))中此解决方案的时间复杂度,因为我们必须对N个项求和,而在最坏的情况下,一个数字的位数是log10(N) 。
使用动态编程的更好方法 (Better approach using Dynamic Programming)
Now, we figure out the solution which takes only log10(N) time. We can use dynamic programming here to find the solution which takes log10(N) time, the optimal substructure for the problem is discussed below:
现在,我们找出仅需log10(N)时间的解决方案。 我们可以在此处使用动态编程来查找耗时log10(N)的解决方案,下面讨论了该问题的最佳子结构:
Let you want to calculate sum(9999) & in order to find it you have to calculate sum(999). To calculate sum(999) you have to find out sum(99) and similarly for sum(99) you have to calculate sum(9).
让您想要计算sum(9999) ,为了找到它,您必须计算sum(999) 。 要计算sum(999),您必须找出sum(99) ,类似地,对于sum(99),您必须计算sum(9) 。
sum(9999)=>sum(999)=>sum(99)=>sum(9)
总和(9999)=>总和(999)=>总和(99)=>总和(9)
sum (10 – 1) = sum(9) = 1 + 2 + 3 + 4 ... + 9 = 45
Similarly ,
sum(100 – 1) = sum(99) = 45 + (10 + 45) + (20 + 45) + ... (90 + 45)
= 45*10 + (10 + 20 + .................+ 80 + 90)
= 45*10 + 10(1 + 2 + ..................+ 8 + 9)
= 45*10 + 10 * 45
= sum(9)*10 + 10*45
sum(1000 – 1) = sum(999) = sum(99)*10 + 100 * 45
so, we can write recursive formula of overlapping
sub-problems for computing sum(10d – 1) as:
sum(10d - 1) = sum(10d-1 - 1) * 10 + 45*(10d-1)
Example explanation using DP:
使用DP的示例说明:
Now, let’s see for N = 3266 i.e we have to find sum of digits of first 3266 numbers.
现在,让我们看一下N = 3266,即我们必须找到前3266个数字的数字总和。
If you want to find sum for N = 3266 then we can think it like this:
如果您想找到N = 3266的总和,那么我们可以这样认为:
Sum of numbers from (0 – 999) + from(1000 – 1999) + from(2000 – 2999) + from(3000 – 3266)
Now it can be written as :
=>sum(999)+ { sum(999) + 1 occur 1000 times } + { sum(999) + 2 occur 1000 times } + {sum(266) + 3 occur 266 times}
=>sum(999) + { sum(999) + 1 * 1000 } + { sum(999) + 2 * 1000 } + {sum(266) + 3 * 266}
=> 3 * sum(999) + (1 + 2 )*1000 + 3 * 266 + sum(266)
Now sum(266) can be written as :
=> sum(0 to 99) + sum(100 to 199) + sum(200 to 266)
=> sum(99) + { sum(99) + 1 * 100 } + { 2 * 66 + sum(66) }
=> 2 * sum(99) + 1*100 + 2 * 66 + sum(66)
从(0 – 999)+从(1000 – 1999)+从(2000 – 2999)+从(3000 – 3266)的数字总和
现在可以写成:
=> sum(999)+ {sum(999)+1发生1000次} + {sum(999)+ 2发生1000次} + {sum(266)+ 3发生266次}
=>总和(999)+ {总和(999)+ 1 * 1000} + {总和(999)+ 2 * 1000} + {总和(266)+ 3 * 266}
=> 3 *和(999)+(1 + 2)* 1000 + 3 * 266 +和(266)
现在sum(266)可以写成:
=> sum(0到99)+ sum(100到199)+ sum(200到266)
=> sum(99)+ {sum(99)+1 * 100} + {2 * 66 + sum(66)}
=> 2 *和(99)+ 1 * 100 + 2 * 66 +和(66)
Now observe the pattern here:
现在在这里观察模式:

Algorithm: Now, see algorithm for solving above problem.
算法:现在,请参阅解决上述问题的算法。
calculate_sum(d)
{
a[0] = 0
a[i] = 45
for(i=2 to d)
{
a[i] = a[i-1]*10 + 45*10^(i-1)
}
}
sum_of_digits(N)
{
d = log(N)
if (N<10)
return N*(N+1)/2
//now calculate sum of digits from
//1 to 10^d-1 using calculate_sum()
//function
lmd = N/10^d // left most digit
return lmd * a[d] + (lmd*(lmd-1)/2) * 10^d +
lmd * (1+N % 10^d) + sum_of_digits(N % 10^d)
}
方案1:解决上述问题的暴力手段 (Program 1: brute force approach for solving above problem)
#include <bits/stdc++.h>
using namespace std;
long long sum(int N)
{
long long sum = 0;
long long i,temp;
for(i =1;i<=N;i++)
{
temp = i;
while(temp != 0)
{
//extracting last digit and adding to sum
sum = sum + temp%10;
//removing digit
temp = temp/10;
}
}
return sum;
}
int main()
{
int N;
cout<<"enter the value of N : ";
cin>>N;
cout << "Sum of digits of first " << N << " natural numbers is = "<<sum(N);
return 0;
}
Output
输出量
enter the value of N : 450
Sum of digits of first 450 natural numbers is = 4734
程序2:在该程序中,我们看到了有效方法的实施 (Program 2: In this program we see the implementation of efficient approach)
#include <bits/stdc++.h>
using namespace std;
int a[100000];
void calculate_sum(int d)
{
a[0] = 0;
a[1] = 45;
for(int i=2;i<=d;i++)
{
//sum(10^d - 1) = sum((10^d-1)-1)*10 + 45 * 10^(d-1)
a[i] = a[i-1]*10 + 45*pow(10,i-1);
}
}
long long sum_of_digits(int N)
{
//base condition
//if N less than 10
//return sum of first N numbers
if (N<10)
return N*(N+1)/2;
//calculating number of digits in N
int d = log10(N);
//calculate sum of digits from 1 to 10^d-1
calculate_sum(d);
//left most digit
int lmd = N/pow(10,d);
//store the value of 10^d
int t = ceil(pow(10,d));
return lmd * a[d] + (lmd*(lmd-1)/2) * t + lmd * (1 + N % t) + sum_of_digits(N % t);
}
int main()
{
int N;
cout<<"enter the value of N : ";
cin>>N;
cout << "Sum of digits of first " << N << " natural numbers is = "<<sum_of_digits(N);
return 0;
}
Output
输出量
enter the value of N : 450
Sum of digits of first 450 natural numbers is = 4734