• 【HDU-6148】 Valley Numer(数位dp)


    百度之星2017复赛1005 HDU-6148 Valley Numer

    题意

    不出现上升后直接下降数位的数,不超过n的有几个。前导零不算。

    题解

    dfs(当前数位的位置len,这位的数num,是否在上升up,是否有限制limit)
    limit不用存到状态里,因为limit为true时不可能访问两次。
    num=-1代表还没开始这个数的第一位,前面是前导零。
    up=1时,不允许下降。

    代码

    #include <bits/stdc++.h>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define ll long long
    #define N 105
    const ll M = 1e9+7;
    using namespace std;
    
    int t;
    char s[N];
    int mlen;
    ll st[N][11][2];
    void add(ll &x,ll v){
        x+=v;if(x>=M)x-=M;
    }
    ll dfs(int len,int num,int up,bool limit);
    void work(int len,int num,int up,bool limit,int i,ll &ans){
        if(num==-1 && i==0){
            add(ans,dfs(len+1,-1,0,limit));
        }else{
            if(num==-1){
                add(ans,dfs(len+1,i,0,limit));
            }else if(i<num){
                if(up==0)
                add(ans,dfs(len+1,i,0,limit));
            }else if(i==num){
                add(ans,dfs(len+1,i,up,limit));
            }else{
                add(ans,dfs(len+1,i,1,limit));
            }
        }
    }
    ll dfs(int len,int num,int up,bool limit){
        if(len==mlen) return num != -1;
        if(!limit && (~num)&&(~st[len][num][up]))return st[len][num][up];
        ll ans=0;
        int b=limit?s[len]-'0':9;
        for(int i=0;i<=b;++i)
            work(len,num,up,i==b&&limit,i,ans);
        return num<0||limit?ans:st[len][num][up]=ans;
    }
    int main(){
        scanf("%d",&t);
        while(t--){
            scanf("%s",s);
            mlen=strlen(s);
            mem(st,-1);
            printf("%lld
    ",dfs(0,-1,0,1));
        }
        return 0;
    }
    
  • 相关阅读:
    本地项目上传至GitHub
    博客园上传markdown格式文章
    Spring boot快速入门
    洛谷P1279 字串距离
    洛谷P2758 编辑距离
    POJ 堆栈基本操作
    洛谷P2815 IPv6地址压缩
    喵的Unity游戏开发之路
    喵的Unity游戏开发之路
    喵的Unity游戏开发之路
  • 原文地址:https://www.cnblogs.com/flipped/p/7391489.html
Copyright © 2020-2023  润新知