windy数 数位dp

这是个裸的数位 d p 吧。

A > B 的就相当于求 ( 1 > B ) ( 1 > ( A 1 ) )

d p [ i ] [ j ] 表示 枚举到第 i 位(从高位到底为枚举,这样更有利于处理上限),前一位是 j 的方案数、

d p [ i ] [ j ] > d p [ i + 1 ] [ ] j 0 ] 要求 j 可以转化成为 j 0

同时我们要记录两个参数: S X (上限),当突破上限时 b r e a k

Q D L 前导零,相当于记录位数

直接记忆化搜索就可以了

#include <bits/stdc++.h>
using namespace std ;

#define clr(a) memset((a),0,sizeof((a)))

typedef long long ll ;

ll a,b ;
ll dp[20][10]; //dp[i][j]表示前i位,前一位为j
int dig[20] ;

ll DP(int k,int last,int SX,int QDL){
    if (k==0) return 1 ;
    if (!QDL && !SX && dp[k][last]!=-1) return dp[k][last];
    int ans=0 ;
    for (int i=0;i<=9;i++){
        if (SX && i>dig[k]) break ;
        if (abs(i-last)<2) continue ;
        int t=i ;
        if (QDL && !i) t=-10;
        ans+=DP(k-1,t,(SX && i==dig[k]),(t==-10)) ;
    }
    if (!SX && !QDL) dp[k][last]=ans ;
    return ans ;
}

ll solve(ll x){
    int dsum=0;
    clr(dig) ;
    memset(dp,-1,sizeof(dp)) ;
    while(x){
        dig[++dsum]=x%10 ;
        x/=10;
    }
    return DP(dsum,-10,1,1) ;
}

int main(){
    scanf("%lld%lld",&a,&b) ;
    ll ans=solve(b)-solve(a-1) ;
    printf("%lld\n",ans) ;
}

猜你喜欢

转载自blog.csdn.net/HQG_AC/article/details/81264911