bzoj 1026: [SCOI2009]windy数【数位dp】

忘记limit不能记WA了一发……
典型数位dp,变成work(r)-work(l-1),然后dfs的时候记录w当前位置,la上一个数选的什么,lm当前位是否有上限,ok当前位是否可以不考虑差大于等于2的情况(前面全是0)
然后对于lm和ok都为0的情况记忆化一下即可
啊bzoj不知道为啥给cmath下的abs判CE……换成algorithm就没事

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=15;
long long l,r,f[N][N],a[N],tot;
long long dfs(int w,int la,int lm,int ok)
{
    if(!lm&&!ok&&f[w][la])
        return f[w][la];
    if(!w)
        return 1;
    long long r=0;
    if(lm)
    {
        for(int i=0;i<=a[w];i++)
            if(abs(la-i)>1||ok)
                r+=dfs(w-1,i,i==a[w],ok&&i==0);
    }
    else
    {
        for(int i=0;i<=9;i++)
            if(abs(la-i)>1||ok)
                r+=dfs(w-1,i,0,ok&&i==0);
    }
    if(!lm&&!ok)
        return f[w][la]=r;
    else
        return r;
}
long long wk(long long x)
{
    tot=0;
    while(x)
        a[++tot]=x%10,x/=10;
    return dfs(tot,13,1,1);
}
int main()
{
    scanf("%lld%lld",&l,&r);
    printf("%lld\n",wk(r)-wk(l-1));
    return 0;
}
posted @ 2018-08-01 22:51  lokiii  阅读(...)  评论(... 编辑 收藏