FZU 2070 - Beautiful number 数位DP..

             题意:

                       一个数前len/2个数字之和和后(len+1)/2数字之和相同称为Beautiful number..现在问A~B有多少个Beautiful number。

             题解:

                      典型的数位dp...我写数位dp总是写得很蛋疼..一定是方法有问题...

                      状态是这样的dp[L][D][M]代表长度为L的数.第一个数字为D.数位之和为M的个数...

                      主要是构造个数的时候有些麻烦...


Program:

#include<iostream>      
#include<algorithm>      
#include<stdio.h>      
#include<string.h>    
#include<time.h>   
#include<map>   
#include<math.h>      
#include<queue>      
#define MAXN 100005
#define MAXM 500005 
#define oo 1000000007      
#define ll long long      
#define MOD 1000000  
using namespace std; 
ll dp[22][12][185];
void PreWork()
{
      int t,x,p,i;
      memset(dp,0,sizeof(dp));
      dp[0][0][0]=1;
      for (t=1;t<=18;t++)
         for (x=0;x<10;x++)
            for (p=0;p<=170;p++)
              for (i=0;i<10;i++)
                dp[t][x][p+x]+=dp[t-1][i][p];              
} 
ll count(ll x)
{
      ll sum=0;
      int len,L,i,j,p,h,t=0;   
      char s[22]; 
      if (x<10) return 0;
      sprintf(s+1,"%I64d",x),len=strlen(s+1);
      L=len/2;  
      for (h=len;h>=1;h--)
      {
              if (!L) L=(len+1)/2;
              if (h>(len+1)/2)
              {
                     if (h==len) i=1;
                            else i=0;
                     for (;i<s[len-h+1]-'0';i++)  
                         for (p=0;p<=170-t;p++)
                            for (j=0;j<10;j++)
                               sum+=dp[L][i][p]*dp[(len+1)/2][j][p+t];
                     t+=s[len-h+1]-'0';
                     L--;
              }else 
              {
                     for (i=0;i<s[len-h+1]-'0';i++) sum+=dp[L][i][t];
                     t-=s[len-h+1]-'0';
                     if (t<0) break;
                     L--;
              }
      }     
      if (!t) sum++;
      for (L=len-1;L>=1;L--)
         for (i=1;i<10;i++)
            for (x=0;x<10;x++)
               for (p=0;p<=170;p++)
                  sum+=dp[L/2][i][p]*dp[(L+1)/2][x][p]; 
      return sum;
}
int main()     
{            
      int C,cases;
      ll A,B; 
      PreWork();
      scanf("%d",&C);
      for (cases=1;cases<=C;cases++)
      {
               scanf("%I64d%I64d",&A,&B);
               printf("%I64d\n",count(B)-count(A-1));
      }
      return 0;    
}    


你可能感兴趣的:(FZU 2070 - Beautiful number 数位DP..)