bzoj1026: [SCOI2009]windy数:http://www.lydsy.com/JudgeOnline/problem.php?id=1026
蒟蒻表示第一次学数位dp…
数位dp的题目大体都是在a到b中找符合的数??
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int f[20][20];//i位 最高位放j (第i位放j)
int s[20];
void emm()//预处理
{
memset(f,0,sizeof(f));
for (int i=0;i<=9;i++) f[1][i]=1;
for (int i=2;i<=10;i++)
{
for (int j=0;j<=9;j++)
{
for (int k=0;k<=9;k++)
{
if (abs(j-k)>=2) f[i][j]+=f[i-1][k];
}
}
}
}
long long solve(long long x)
{
int n=0;long long m=x;
while (m>0)
{
s[++n]=m%10;
m/=10;
}
long long ans=0;
for (int i=1;i<=s[n]-1;i++) ans+=f[n][i];//最高位放比x小的数 贡献
for (int i=1;i<=n-1;i++)
{
for (int j=1;j<=9;j++) ans+=f[i][j];//不放到最高位的 贡献
}
//讨论 f[n][s[n]];
for (int i=n-1;i>0;i--)
{
for (int j=0;j<=s[i]-1;j++)//调了两个小时只因没有-1
{
if (abs(s[i+1]-j)>=2) ans+=f[i][j];
}
if (abs(s[i+1]-s[i])<2) break;
}
//讨论x本身
bool bk=true;
for (int i=1;i<=n-1;i++)
{
if (abs(s[i+1]-s[i])<2) {bk=false;break;}
}
if (bk&&x!=0) ans++;
return ans;
}
int main()
{
long long a,b;
scanf("%lld%lld",&a,&b);
emm();
long long ans;
ans=solve(b)-solve(a-1);//前缀和思想
printf("%lld\n",ans);
return 0;
}