• 【hdu6148】Valley Numer【数位dp模板题】


    题意

      对于每组数据给出一个整数n(length(n)<=100),找出不大于n的数字中有多少是Valley Numer。对于Valley的定义是它每一位的数字要么是递增,要么是递减,要么是先递减后递增

    分析

      选拔赛的时候遇到了数位dp,以前只是听说但是没学过今天就拿出来一天的时间学了一下数位DP。

      我们发现单调递减变为单调递增合法,单调递增变为递减不合法,所以通过增减判断最多只有一个拐点。那么我们在dp的时候状态只要记录当前是递增还是递减就可以了。

      我们用dp[p][pre][state]来进行记忆化。p代表的是位数,pre代表的是上一位的值,state代表是递减还是递增。

      这个算是数位dp很板子的一个题目,但是我一开始一直wa,感觉自己考虑的很对,然后最后看题解发现自己没有考虑前导0.

      我们发现,当存在前导0的时候,相当于从这里新开一个数字,那么当前是递增还是递减就不确定了,没法根据前面的0来判断,所以当存在前导0的时候步可以记忆化否则会因为dp数组的冲突而导致答案错误。

      

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 
     6 using namespace std;
     7 typedef long long LL;
     8 const int mod=1000000007;
     9 const int maxn=100+10;
    10 int n,a[maxn],pos,T;
    11 char s[maxn];
    12 LL dp[maxn][10][2];//0 上升 1 下降
    13 LL dfs(int p,int pre,int state,int lead,int limit){
    14     if(p==0){
    15         if(lead)
    16             return 0;
    17         return 1;
    18     }
    19     if(!limit&&dp[p][pre][state]!=-1&&!lead)
    20         return dp[p][pre][state];
    21     int up=limit?a[p]:9;
    22     LL res=0;
    23     for(int i=up;i>=0;i--){
    24         if(state==0&&i<pre)
    25             continue;
    26         int st;
    27         if(i==pre)st=state;
    28         else if(i<pre)st=1;
    29         else st=0;
    30         if(lead)st=1;
    31         res=(res+dfs(p-1,i,st,lead&&i==0,limit&&i==a[p]))%mod;
    32     }
    33     if(!limit&&!lead)
    34         dp[p][pre][state]=res;
    35     return res;
    36 }
    37 LL solve(){
    38     pos=0;
    39     for(int i=n-1;i>=0;i--){
    40         pos++;
    41         a[pos]=s[i]-'0';
    42     }
    43     memset(dp,-1,sizeof(dp));
    44     return dfs(pos,0,0,1,1);
    45 }
    46 int main(){
    47     scanf("%d",&T);
    48     for(int t=1;t<=T;t++){
    49         scanf("%s",s);
    50         n=strlen(s);
    51         printf("%lld
    ",solve()%mod);
    52     }
    53 return 0;
    54 }
    View Code
  • 相关阅读:
    eclipse设置字体大小
    如何利用服务器下发的Cookie实现基于此Cookie的会话保持
    Docker学习笔记_安装和使用Python
    Docker学习笔记_安装和使用mysql
    Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.38/images/json: dial unix /var/run/docker.sock: conne
    Ubuntu18.04创建新的系统用户
    Docker学习笔记_安装和使用nginx
    Docker安装和使用Tomcat
    虚拟机ubuntu18.04设置静态IP
    我学习参考的网址
  • 原文地址:https://www.cnblogs.com/LQLlulu/p/9649713.html
Copyright © 2020-2023  润新知