题目大意:自行参考。
题解:
设dp[i][j][2][2][2]表示考虑到第i位,数字是j,是否紧贴上界,历史上是否存在一个差小于2,以及这i位是否全部为0.
为什么要记录最后一个“是否全部为0”呢?原因是如果前i位全部为0那么第i+1位无论是什么数都满足要求;
否则如果第i位是0但是前i-1位不全为0那么意味着第i+1位只能是2及以上。
注意到如果前i位都是0的话那么历史上就不存在一个差小于2,并且一定不会紧贴上界,所以部分状态就不用考虑转移了(因为他们不合法)
转移方程我一共推了5个。
代码:
//SCOI 2009
//BZOJ 1026
#include<iostream>
#include<cstring>
#include<cstdio>
#define gabs(x) (((x)>0)?(x):(-(x)))
#define f(x) ((int)(gabs(x)>=2))
#define MAXN 20
using namespace std;
int a[MAXN],n,dp[MAXN][10][2][2][2];
int getlist(int A)
{
n=0;
while(A)
{
a[++n]=A%10;
A/=10;
}
for(int i=1;i<=n/2;i++)
swap(a[i],a[n-i+1]);
return 0;
}
int getdp(int A)
{
getlist(A);
if(!n) return 1;
for(int i=1;i<=n;i++)
for(int j=0;j<=9;j++)
dp[i][j][0][0][0]=dp[i][j][0][0][1]
=dp[i][j][0][1][0]=dp[i][j][0][1][1]
=dp[i][j][1][0][0]=dp[i][j][1][0][1]
=dp[i][j][1][1][0]=dp[i][j][1][1][1]=0;
dp[1][0][0][1][0]=1;
for(int i=1;i<a[1];i++)
dp[1][i][0][1][1]=1;
dp[1][a[1]][1][1][1]=1;
for(int i=1;i<n;i++)
for(int j=0;j<=9;j++)
for(int k=0;k<=9;k++)
{
int p=f(k-j),t=(k==a[i+1]);
dp[i+1][k][0][0][1]+=dp[i][j][0][0][1];
dp[i+1][k][0][1][k>0]+=dp[i][j][0][1][0];
dp[i+1][k][0][p][1]+=dp[i][j][0][1][1];
if(j==a[i]&&k<=a[i+1])
{
dp[i+1][k][t][0][1]+=dp[i][j][1][0][1];
dp[i+1][k][t][p][1]+=dp[i][j][1][1][1];
}
}
int ans=0;
for(int j=0;j<=9;j++)
ans+=dp[n][j][0][1][0]+dp[n][j][0][1][1];
ans+=dp[n][a[n]][1][1][0]+dp[n][a[n]][1][1][1];
return ans;
}
int main()
{
int a,b;scanf("%d%d",&a,&b);
int ans=getdp(b)-getdp(a-1);
printf("%d\n",ans);return 0;
}