f [ i ] [ j ] f[i][j] f[i][j]表示长度为 i i i并且最高位为 j j j的windy数的个数。
递推关系: f [ i ] [ j ] = ∑ f [ i − 1 ] [ k ] a b s ( j − k ) ≥ 2 f[i][j]=\sum f[i-1][k]\ \ \ \ \ \ \ abs(j-k)\geq2 f[i][j]=∑f[i−1][k] abs(j−k)≥2
然后我们举个例子来讨论:我们接下来要求 ≤ 32467 \leq 32467 ≤32467的windy数的个数。
首先我们用 w [ ] w[] w[]来存储 32467 32467 32467的位数,即: w [ 1 ] = 7 , w [ 2 ] = 6 , w [ 3 ] = 4 , w [ 4 ] = 2 , w [ 5 ] = 3 w[1]=7,w[2]=6,w[3]=4,w[4]=2,w[5]=3 w[1]=7,w[2]=6,w[3]=4,w[4]=2,w[5]=3
① 我们可以累加答案 a n s + = ∑ i = 1 4 ∑ j = 1 9 f [ i ] [ j ] ans+=\sum_{i=1}^{4}\sum_{j=1}^{9}f[i][j] ans+=∑i=14∑j=19f[i][j]
表示我们统计完位数不超过 4 4 4的windy数的个数,
一般地, a n s + = ∑ i = 1 l e n − 1 ∑ j = 1 9 f [ i ] [ j ] ans+=\sum_{i=1}^{len-1}\sum_{j=1}^9f[i][j] ans+=∑i=1len−1∑j=19f[i][j]
② 累加答案 a n s + = ∑ i = 1 2 f [ 5 ] [ i ] ans+=\sum_{i=1}^{2}f[5][i] ans+=∑i=12f[5][i]
表示我们统计完位数为 5 5 5并且最高位 ≤ 2 \leq 2 ≤2的windy数的个数,我们可以这样统计的原因是原来的数包含了这一部分并且这一部分与①不重复。
一般地, a n s + = ∑ i = 1 w [ l e n ] − 1 f [ l e n ] [ i ] ans+=\sum_{i=1}^{w[len]-1}f[len][i] ans+=∑i=1w[len]−1f[len][i]
③ 接下来我们考虑剩下的一部分。
我们从第二高位开始向低位枚举。
显然 31 x x x 31xxx 31xxx这种形式的windy数的个数与 f [ 4 ] [ 1 ] f[4][1] f[4][1]相同,于是对于第 i i i位,我们可以从 0 0 0开始枚举到 w [ i ] − 1 w[i]-1 w[i]−1,判断与 w [ i + 1 ] w[i+1] w[i+1]的关系进行答案累加。
而在这中间我们并不直接枚举到 w [ i ] w[i] w[i]是因为此时的这个范围并不被完全包含。然后我们枚举到 w [ i ] − 1 w[i]-1 w[i]−1之后,进行判断 a b s ( w [ i + 1 ] − w [ i ] ) abs(w[i+1]-w[i]) abs(w[i+1]−w[i])与 2 2 2的大小关系。如果 a b s ( w [ i + 1 ] − w [ i ] ) < 2 abs(w[i+1]-w[i])<2 abs(w[i+1]−w[i])<2就整个累加结束,这是因为如果 a b s ( w [ i + 1 ] − w [ i ] ) < 2 abs(w[i+1]-w[i])<2 abs(w[i+1]−w[i])<2那么之后的所有数都会包含这个也就不符合条件了。
④ 累加完之后考虑一下这个数本身是否被考虑进去了。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define rep(i,x,y) for(ll i=(x);i<=(y);i++)
#define repl(i,x,y) for(ll i=(x);i<(y);i++)
#define repd(i,x,y) for(ll i=(x);i>=(y);i--)
using namespace std;
const ll N=25;
const ll Inf=1e18;
ll l,r,w[N],f[N][N];
inline ll read() {
ll x=0;char ch=getchar();bool f=0;
while(ch>'9'||ch<'0'){if(ch=='-')f=1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?-x:x;
}
void split(ll x) {
w[0]=0;
while(x) {
w[++w[0]]=x%10;x/=10;
}
}
ll calc(ll x) {
ll ans=0;
split(x);
rep(i,1,w[0]-1) rep(j,1,9) ans+=f[i][j];
rep(i,1,w[w[0]]-1) ans+=f[w[0]][i];
repd(i,w[0]-1,1) {
rep(j,0,w[i]-1) if(abs(j-w[i+1])>=2) ans+=f[i][j];
if(abs(w[i+1]-w[i])<2) break;
if(i==1) ans++;
}
return ans;
}
int main() {
rep(i,0,9) f[1][i]=1;
rep(i,2,N-1) rep(j,0,9) rep(k,0,9) if(abs(j-k)>=2) f[i][j]+=f[i-1][k];
l=read(),r=read();
printf("%lld\n",calc(r)-calc(l-1));
return 0;
}