计算给定N的从1到N的所有数字的数字总和

这篇博客介绍了如何使用动态编程有效地计算从1到N所有数字的数字总和,对比了暴力求解方法,并提供了更优的解决方案,时间复杂度为O(log10(N))。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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:

现在在这里观察模式:

Computer sum of digits

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


翻译自: https://www.includehelp.com/algorithms/compute-sum-of-digits-in-all-numbers-from-1-to-n-for-a-given-n.aspx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值