题目:BZOJ1026、洛谷P2657。
题目大意:
给你(A,B),求([A,B])中满足:没有前导0且相邻两位的数字相差至少为2的整数 的个数。
解题思路:
数位DP。
设(DP{i,j})表示(i)位,最高位为(j)((j可以为0))并满足条件的个数。
则(DP{i,j}=sumlimits_{k=0}^9 DP_{i-1,k} imes [|j-k|>1])
边界:(DP_{1,x}=1)。
然后分别计算(1~A-1)和(1~B)中满足条件的个数,相减即可。(BZOJ不资瓷C++11差评)
C++ Code:
#include<cstdio>
typedef int I;
I a,b,dp[15][15],dd[15];
inline I abs(const I a){return a<0?-a:a;}
void init(){
for(I i=9;~i;--i)dp[1][i]=1;
for(I i=1;10/++i;){
for(I j=9;~j;--j)
for(I k=9;~k;--k)
if(abs(j-k)>1)dp[i][j]+=dp[i-1][k];
}
}
inline I calc(I x){
I len=0,ans=0;
for(;x;x/=10)dd[++len]=x%10;
for(I i=len;--i;)
for(I j=9;j;--j)ans+=dp[i][j];
for(I i=1;dd[len]>i;++i)ans+=dp[len][i];
for(I i=len;--i;){
for(I j=0;j<dd[i];++j)
if(abs(dd[i+1]-j)>1)ans+=dp[i][j];
if(abs(dd[i+1]-dd[i])<2)break;
}
return ans;
}
I main(){scanf("%d%d",&a,&b);init();return!printf("%d
",calc(b+1)-calc(a));}