题解:UVA12517 Digit Sum

数位 dp 模板题……

题目大意

给你两个数 l,rl,r,求出 l,rl,r 之间所有数的数位和。

什么是数位和?

举个栗子,有一个数 123123,那么他的数位和,即各个数位的和为 6(1+2+3)6(1+2+3)

考虑求数位和,采用数位 dp(不会请移步P4999)。

简单分析一下。

  • 定义状态:

dpi,jdp_{i,j}:以 jj 作为最高位的 ii 位数的数字和。

性质:以 xx 作为最高位的 yy 位数有 10y110^{y-1} 个。

  • 求状态转移方程:

dpi,j=(dpi1,0/1/2/3/4/5/6/7/8/9)+j10i1dp_{i,j}=(\sum{dp_{i-1,0/1/2/3/4/5/6/7/8/9}})+j*10^{i-1}

  • 边界条件:

dp0,0=0dp_{0,0}=0

那么接下来就是直接上模板了:

#include<bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;
const int mod=1e9+7;
int dp[200][200];
int t;
void init(){
	dp[0][0]=0;
	for(int i=1;i<=19;i++){
		for(int j=0;j<=9;j++){
			for(int k=0;k<=9;k++){
				dp[i][j]+=dp[i-1][k];
			}
			int sum=1;
			for(int k=1;k<=i-1;k++){
				sum*=10;
			}
			dp[i][j]+=j*sum;
		}
	}
}
int query(int x){
	int num[25]={0},ans=0,sum=0,cnt=0;
	while(x!=0){
		cnt++;
		num[cnt]=x%10;
		x/=10;
	}
	for(int i=cnt;i>=1;i--){
		for(int j=0;j<=num[i]-1;j++){
			ans+=dp[i][j];
			int tmp=1;
			for(int k=1;k<=i-1;k++){
				tmp=tmp*10;
			}
			ans+=sum*tmp;
		}
		sum+=num[i];
	}
	return (ans+sum);
}
signed main(){
	init();
	while(1){
		int l,r;
		cin>>l>>r;
		if(l==0&&r==0)return 0;
		cout<<query(r)-query(l-1)<<endl;
	}
	return 0;
}
*/
posted @   KK_SpongeBob  阅读(3)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 百万级群聊的设计实践
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
点击右上角即可分享
微信分享提示