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 <= 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
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];
由于每一位上都有数的限制,我们可以选择先把这一位上的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\n",s[1]);

    //printf("%d\n",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("\n");

     }*/

     //for(int i=2;i<=len;i++)

       // dp[i][0]+=dp[i-1][0];

   //  for(int i=1;i<=len;i++)

       // printf("%lld\t",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("\n");

       for(int i=1;i<=yy;i++)

        printf("%d",d[i]);

       printf("\n");*/

     //  printf("%lld\n",answer2);

      // printf("%lld\n",answer1);

       printf("Case #%d: %I64d\n",i,answer2-answer1);

   }

    return 0;

}

 

 

你可能感兴趣的:(HDU)