FZU 2070 - Beautiful number 数位DP..
原创
©著作权归作者所有:来自51CTO博客作者zzyzzy12的原创作品,请联系作者获取转载授权,否则将追究法律责任
题意:
一个数前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;
}