If we sum up every digit of a number and the result can be exactly divided by 10, we say this number is a good number.
You are required to count the number of good numbers in the range from A to B, inclusive.
Input
The first line has a number T (T <= 10000) , indicating the number of test cases.
Each test case comes with a single line with two numbers A and B (0 <= A <= B <= 10 18).
Output
For test case X, output "Case #X: " first, then output the number of good numbers in a single line.
Sample Input
2
1 10
1 20
Sample Output
Case #1: 0
Case #2: 1
题意
给你两个数a,b ,让你求出a,b之间有多少数是幸运数
幸运数的规定:数的每个位置上的数的和是取余10为0;
思路
看到题就感觉是数位dp,比赛的时候脑子瓦特了。。。没有打出来(好像找规律也是可以的)
先用数位dp算一下1~b之间符合题意的个数,然后减去1 ~a-1之间符合题意的个数就是答案了。
数位dp就是把每一位拆开来看,从网上找了一张图可以稍微理解一下数位dp
数位dp我用的是记忆化搜索;
dp[pos][sta]:第pos位上现在状态为sta时符合题意的个数;
sta:之前所有枚举到的数的和取余10;
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
long long dp[25][15];
int th[24];
long long shudp(int pos,int sta,int flag)
{
if(pos==-1)//最后一位返回
return sta==0;
if(!flag&&dp[pos][sta]!=-1)//剪枝
return dp[pos][sta];
int up=flag?th[pos]:9;
long long ans=0;
for(int i=0; i<=up; i++)
{
ans+=shudp(pos-1,(sta+i)%10,flag&&i==up);
}
if(flag)//判断是不是上界
return ans;
else
return dp[pos][sta]=ans;
}
long long init(long long x)//先将每一位数存爱数组里
{
int cnt=0;
while(x)
{
th[cnt++]=x%10;
x/=10;
}
return shudp(cnt-1,0,1);
}
int main()
{
memset(dp,-1,sizeof(dp));
int T;
long long a,b;
int p=1;
scanf("%d",&T);
while(T--)
{
scanf("%lld %lld",&a,&b);
printf("Case #%d: ",p++);
if(a==0)//0要特判
printf("%lld\n",init(b));
else
{
long long ans=init(b);
ans-=init(a-1);
printf("%lld\n",ans);
}
}
return 0;
}