专栏文章

题解:UVA12517 Digit Sum

UVA12517题解参与者 5已保存评论 6

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
6 条
当前快照
1 份
快照标识符
@mioizxg1
此快照首次捕获于
2025/12/02 19:59
3 个月前
此快照最后确认于
2025/12/02 19:59
3 个月前
查看原文

题解:UVA12517 Digit Sum

思路

我们可以计算 00NN 的数位和之和以及 00MM 的数位和之和,然后相减,最后再加上被减去的 NN 的数位和。
就拿 328328 这个数来讲吧,计算 00328328 的数位和之和,我们可以将它先拆解为 00300300 的数位和之和、300300328328 的数位和之和。
  • 先算 00300300 的数位和之和:从百位来看,1122 都被计算了 100100 次,33 被计算了 11 次;从十位来看,从 1199100100 个数就会被计算 1010 次,而 300300 就被计算了 3030 次;从个位来看,从 11991010 个数就会被计算 11 次,而 300300 就也被计算了 3030 次,由此得出,计算 00300300 的数位和之和的算式为:3+(1+2)×100+30×[(1+9)×9÷2]×2=30033 + ( 1 + 2 ) \times 100 + 30 \times [ ( 1 + 9 ) \times 9 \div 2 ] \times 2 = 3003
  • 再算 300300328328 的数位和之和:可以将它看成 002828 的数位和之和加上少算的 282833
所以得出:设 00NN 的数位和之和为 f(n)f(n) ,NN 的长度设为 lenlen,第一个数设为 firstfirst,除第一个数外后面的数为 behindbehind,就可以得出这样的式子:
f(n)=first×(behind+1)+f(behind)+[(first1)×first÷2]×10len1+first×10len2×[(1+9)×9÷2]×(len1)f(n) = first \times ( behind + 1 ) +f(behind) + [ ( first - 1 ) \times first \div 2 ] \times 10 ^ { len - 1 } + first \times 10 ^ { len - 2 }\times [ ( 1 + 9 ) \times 9 \div 2 ] \times ( len - 1 )
当然啦,当 lenlen11f(n)=(1+n)×n÷2f(n) = ( 1 + n ) \times n \div 2。 所以递归就写出来了:
CPP
long long solve(long long n){
	if(n<10){
		return (1+n)*n/2;
	}
	long long final_out=0;
	long long v=n;
	long long len=0;
	while(v>0){
		len++;
		final_out+=v%10;;
		v/=10;
	}
	long long first=n/(long long)pow(10,len-1);
	long long behind=n%(long long)pow(10,len-1);
	return first*(behind+1)+solve(behind)+(first-1)*first/2*(long long)pow(10,len-1)+first*(len-1)*(long long)pow(10,len-2)*45;
}
没试过不开 long long,可以去试试看的。
还有一个注意的点,我们这里的函数算的数位和是包含 nn 的,所以在之后的相减中要将 NN 的数位和加回来(上文说过了)。
最后的最后,提供一下完整的代码吧。
CPP
#include<bits/stdc++.h>
using namespace std;
long long solve(int n){
	if(n<10){
		return (1+n)*n/2;
	}
	long long final_out=0;
	long long v=n;
	long long len=0;
	while(v>0){
		len++;
		final_out+=v%10;;
		v/=10;
	}
	long long first=n/(long long)pow(10,len-1);
	long long behind=n%(long long)pow(10,len-1);
	return first*(behind+1)+solve(behind)+(first-1)*first/2*(long long)pow(10,len-1)+first*(len-1)*(long long)pow(10,len-2)*45;
}
int main()
{
	while(true){
		long long N,M;
		cin>>N>>M;
		if(N==M && N==0){
			break;
		}
		long long num=0;
		num=solve(M)-solve(N);
		while(N>0){
			num+=N%10;
			N/=10;
		}
		cout<<num<<endl;
	}
	return 0;
}

评论

6 条评论,欢迎与作者交流。

正在加载评论...