题解 BZOJ1026 & luogu P2657 [SCOI2009]windy数 数位DP

BZOJ & luogu

看到某大佬AC,本蒟蒻也决定学习一下玄学的数位$dp$

(以上是今年3月写的话(叫我鸽神$qwq$))


 

思路:数位$DP$

提交:2次

题解:(见代码) 

#include<cstdio>
#include<iostream>
#include<cstring>
#define R register int
using namespace std;
int a,b,f[12][10],num[11];
//f[i][j]搜到第i位,前一位是j,且没有上界标记的方案数 
inline int max(int a,int b){return a>b?a:b;}
inline int abs(int x){return x>0?x:-x;}
int dfs(int l,bool ul,bool ck,int lst) {//l位数,ul上界标记,ck前导零标记,lst上一位 
    if(!l) return 1;
    if(!ul&&(~f[l][lst])) return f[l][lst];//记忆化 
    R mx=ul?num[l]:9,cnt=0;//mx是上界 
    for(R i=0;i<=mx;++i) {
        if(abs(lst-i)<2) continue;//差小于2 
        if(ck&&i==0) cnt+=dfs(l-1,ul&&i==mx,true,-2);//若一直是前导零 
        else cnt+=dfs(l-1,ul&&i==mx,false,i); 
    } return ul||ck?cnt:f[l][lst]=cnt;
}
inline int solve(int x) {
    R len=0; memset(f,0xff,sizeof(f));
    for(;x;x/=10) num[++len]=x%10;//分解每一位
    return dfs(len,true,true,-2);
}
signed main() {
    scanf("%d%d",&a,&b);
    printf("%d\n",solve(b)-solve(a-1));//前缀和减一下 
}

2019.07.18

posted @ 2019-07-18 17:11  LuitaryiJack  阅读(270)  评论(1编辑  收藏  举报