hdu 4722 (数位DP)

Good Numbers

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3360    Accepted Submission(s): 1064

Problem Description
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 <= 1018).
 
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
Hint
The answer maybe very large, we recommend you to use long long instead of int.
 
Source
 
Recommend
zhuyuanchen520   |   We have carefully selected several similar problems for you:  5235 5234 5233 5232 5231 
题目描述:假设一个数每位数上之和能被10整除,称这个数为好数,给定两个数,求在这个范围内的好数.
可以找规律,也可以采用递推。
设d[i][j]表示以i长度的对10取余为j的数的数量。
d[i+1][(j+k)%10]+=d[i][j];
通过d[i][j]进行递推,j代表的是余数,从0到9进行枚举,
由于每一位上都有数的限制,我们可以选择先把这一位上的0到9全部枚举,然后减去超过这个数的,或者先把之前一位的数先枚举到比它那个数小的范围,这一位从0到9枚举
,然后加上。
答案应该是d[r][0]-d[l-1][0],之前写错了。
#include <cstdio>
#include <iostream>
#include <cstring>
#include<vector>
#include<algorithm>
#define  LL  long long
#define maxn 10
#define MAXN 100000
#define inf 0x3f3f3f3f3f3f3f
using namespace std;
LL dp[20][20];
int c[20],d[20];
LL x,y;
LL xx,yy;
void init()
{
  memset(dp,0,sizeof(dp));
}
int getnum(LL num,int  s[])
{
    int t=1;
    while(num>0)
    {
        s[t++]=num%10;
        num/=10;
    }
    for(int i=1;i<=(t-1)/2;i++)
        swap(s[i],s[t-i]);
    return t-1;
}
LL solve(LL len,int *s)
{

   // printf("%d
",s[1]);
    //printf("%d
",s[2]);
     for(int i=0;i<=s[1];i++)
        dp[1][i]=1;
        int x=s[1];
    for(int i=1;i<=len-1;i++)
    {
        for(int j=0;j<=9;j++)
      {
          for(int k=0;k<=9;k++)
        {
          /*if(i==1 && j==0)
          continue;*/
          dp[i+1][(j+k)%10]+=dp[i][j];
        }
      }
      for(int pp=s[i+1]+1;pp<=9;pp++)
      {
          int t=(x+pp)%10;
          dp[i+1][t]--;
      }
      x=(x+s[i+1])%10;
    }

    /* for(int i=1;i<=len;i++)
     {
         for(int j=0;j<=9 ;j++)
         {
             printf("%lld ",dp[i][j]);
         }
         printf("
");
     }*/
     //for(int i=2;i<=len;i++)
       // dp[i][0]+=dp[i-1][0];
   //  for(int i=1;i<=len;i++)
       // printf("%lld	",dp[i][0]);*/
        return dp[len][0];

}
int main()
{
   int T;
   scanf("%d",&T);
   for(int i=1;i<=T;i++)
   {
       init();
       scanf("%I64d%I64d",&x,&y);
       xx=getnum(x-1,c);
       yy=getnum(y,d);
       LL answer1,answer2;
       answer1=solve(xx,c);
       memset(dp,0,sizeof(dp));
       answer2=solve(yy,d);
      /* for(int i=1;i<=xx;i++)
        printf("%d",c[i]);
         printf("
");
       for(int i=1;i<=yy;i++)
        printf("%d",d[i]);
       printf("
");*/
     //  printf("%lld
",answer2);
      // printf("%lld
",answer1);
       printf("Case #%d: %I64d
",i,answer2-answer1);
   }
    return 0;
}
 
原文地址:https://www.cnblogs.com/xianbin7/p/4530837.html