动态规划-数位DPwindy
https://vjudge.net/contest/297216?tdsourcetag=s_pctim_aiomsg#problem/L
#include<bits/stdc++.h>
//#include<math.h>
//#include<stdio.h>
using namespace std;
#define LL long long
const int maxn=2e9+10;
LL f[20][20]; // 设f[i,j]表示由前i位数字构成且最高位数字为j的windy数有多少个
LL a[20];
void init() // 预处理f[i,j]数组
{
for(int i=0; i<=9; i++)
f[1][i]=1;
for(int i=2; i<=15; i++)
{
for(int j=0; j<=9; j++)
{
int l=j-2,r=j+2;
for(int k=l; k>=0; k--)
f[i][j]+=f[i-1][k];
for(int k=r; k<=9; k++)
f[i][j]+=f[i-1][k];
}
}
}
int fun(LL t) // 这个来求[1-t]区间之间有多少winfy数
{
if(t<10) return t;
int len=0;
while(t)
{
a[++len]=t%10;
t/=10;
}
LL sum=0; // 首先,求位数小于这个数的所有windy数
for(int i=1; i<len; i++)
for(int j=1; j<=9; j++)
sum+=f[i][j];
// 求位数等于这个数,最高位小于这个数的最高位的windy数
for(int i=1; i<a[len]; i++)
sum+=f[len][i];
for(int i=len-1; i>=1; i--)
{
for(int j=0; j<=9; j++)
{
if(abs(j-a[i+1])>=2&&j<a[i])
sum+=f[i][j];
}
if(abs(a[i+1]-a[i])<2)
break;
if(i==1)++sum; // 这里注意如果最后一位也满足与上一位差值>=2,需要+1
}
return sum;
}
int main()
{
init();
LL a,b;
scanf("%lld%lld",&a,&b);
LL sum1=fun(b);
LL sum2=fun(a-1);// 这里注意因为要取到a,所有求a-1之前的数
printf("%lld",sum1-sum2);
}