题目描述
不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。问在A和B之间,包括A和B,总共有多少个windy数?
题目分析
之前做了一道板题后再做这道感到愉悦多了。
一样的套路,分解一下题目
[A,B]=[1,B]−[1,A−1]
。对于
[1,x]
,
首先当数的位数小于x时,可以随便取值,我们不妨设
dpi,j=Σ9k=0dpi−1,k
表示位数为
i
,最后一位为
当位数和x相等时,
i
从高到低枚举当前位
需要注意的是当
abs(limi+1−limi)<2
时,停止枚举
i−1
,因为当我们枚举第
i
位时,实际上是在枚举
又及,这么算出来的因为每一次都不达到上界,是
[1,x)
,算的时候算
[1,r+1)−[1,l)
就行了。
代码
/**************************************************************
Problem: 1026
User: szpszp
Language: C++
Result: Accepted
Time:4 ms
Memory:1288 kb
****************************************************************/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define MAXN
#define MAXM
#define INF 0x3f3f3f3f
typedef long long int LL;
template<class T>
void Read(T &x){
x=0;char c=getchar();bool flag=0;
while(c<'0'||'9'<c){if(c=='-')flag=1;c=getchar();}
while('0'<=c&&c<='9'){x=x*10+c-'0';c=getchar();}
if(flag)x=-x;
}
int dp[12][10];
int num[12];
int len;
void getnum(int x){
len=0;
while(x)num[++len]=x%10,x/=10;
}
int Solve(int x){
getnum(x);
int rn=0;
for(int i=1;i<len;++i)
for(int j=1;j<10;++j)rn+=dp[i][j];
for(int j=1;j<num[len];++j)rn+=dp[len][j];
for(int i=len-1;i>=1;--i){
for(int j=0;j<num[i];++j)
if(abs(num[i+1]-j)>=2)rn+=dp[i][j];
if(abs(num[i+1]-num[i])<2)break;
}
return rn;
}
void init(){
for(int i=0;i<10;++i)dp[1][i]=1;
for(int i=2;i<12;++i)
for(int j=0;j<10;++j){
dp[i][j]=0;
for(int k=0;k<10;++k)
if(abs(j-k)>=2)dp[i][j]+=dp[i-1][k];
}
}
int main(){
init();
int l,r;
Read(l),Read(r);
printf("%d\n",Solve(r+1)-Solve(l));
}