题目信息:http://acm.hdu.edu.cn/showproblem.php?pid=4722
题解:题目还是要自己读的。
我的思路:这道题有两种方法,一种是找规律(这里不做讲解,因为这不是同解),下面一种方法就是这类题的通解了,就是数位dp,数位dp,顾名思义就是用来解决数论方面的问题的,其实就是开一个数组存每一位找到的结果而已。下面直接贴上代码。
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
#define ll long long
ll dp[10000];
ll digit[100];
ll dfs(ll point, ll flag, ll sum) // point代表现在dp的位置比如123这个数,point最开始为3代表1所在的位置, flag是标记的作用
//还是以123为例,判断在dp在3位置时,2位置能取到2还是取到9, sum是计算个位置的数的和;
{
if(!point) return sum%10==0; //当point为0时说明已经遍历到各位了,如果此时sum%10==0,就加到结果上去
if(!flag&&dp[point]) return dp[point]; //调用已经保存过的结果
ll len = flag?digit[point]:9, ans = 0;
for(ll i = 0; i <= len; i++)
{
ans += dfs(point-1, flag&&i==len, sum+i); //加上每次遍历的结果,sum%10==0,就加1,否则加0;
}
if(!flag) dp[point] = ans; // 记录结果,截枝;
return ans;
}
ll get_digit(ll x)
{
ll cont = 0;
while(x)
{
digit[++cont] = x%10;
x /= 10;
}
return dfs(cont, 1, 0);
}
int main()
{
ll T, cont = 0;
scanf("%lld", &T);
while(T--)
{
cont++;
ll l, r;
scanf("%lld%lld", &l, &r);
printf("Case #%lld: %lld\n", cont, get_digit(r)-get_digit(l-1));
}
}