题解 P2657 【[SCOI2009]windy数】
一道裸的数位DP题
pos记录搜到了数的第几位,pre记录前一位是哪个数字,lead记录上一位是不是前导零,limit记录上一位是否有最高位限制(也就是这位是否有可能超出搜索的上限)。
#include <bits/stdc++.h>
#define debug printf("Running %s on line %d...\n",__FUNCTION__,__LINE__)
#define in inline
#define re register
using namespace std;
typedef long long ll;
typedef double db;
in int read()
{
int ans=0,f=1;char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
for (;isdigit(c);c=getchar()) ans=(ans<<3)+(ans<<1)+(c^48);
return ans*f;
}
int a[15],len;
int f[15][15];
int dfs(int pos,int pre,int lead,int limit)
{
if (pos>len) return 1;
if ((!lead)&&(!limit)&&(f[pos][pre]!=-1)) return f[pos][pre];
int res=limit?a[len-pos+1]:9;
int ans=0;
for (int i=0;i<=res;i++)
{
if ((!lead)&&abs(i-pre)<2) continue;
ans+=dfs(pos+1,i,(lead&&!i),limit&&(i==res));
}
return ((!lead)&&(!limit))?f[pos][pre]=ans:ans;
}
int solve(int x)
{
len=0;
while (x) a[++len]=x%10,x/=10;
memset(f,-1,sizeof(f));
return dfs(1,0,1,1);
}
int main()
{
int a=read(),b=read();
cout<<solve(b)-solve(a-1)<<endl;
return 0;
}