【算法】数位DP

【题意】定义V-number为从左到看单位数字未出现先递增后递减现象的数字,求0~N中满足条件的数字个数。T<=200,lenth(n)<=100

【题解】百度之星2017复赛,作为送分题出现,拿来练数位DP模板了。

位数多,读入记得用字符串。

记忆化要将有关变量全部纳入。

需要取模的时候别习惯性写"+=",特别是竞速赛,改起来很难受。

-1的变量前加~就和0一样了。

最后自己造数据测试了一下,记忆化搜索的速度简直全面碾压递推啊!(从此坚定了信仰)

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype>
#define ll long long
using namespace std;
const ll maxn=,MOD=;
ll f[maxn][][],a[maxn],n; ll dfs(ll pos,ll state,ll limit,ll pre){
if(pos==-){if(~pre)return ;else return ;}
if(!limit&&~pre&&~f[pos][state][pre])return f[pos][state][pre];
ll up=limit?a[pos]:;
ll ans=;
for(int i=;i<=up;i++){
if(pre==-&&i==)ans=(ans+dfs(pos-,state,limit&&i==up,pre))%MOD;else
if(pre==-&&i!=)ans=(ans+dfs(pos-,state,limit&&i==up,i))%MOD;else
if(state==)ans=(ans+dfs(pos-,i>pre,limit&&i==up,i))%MOD;else
if(state==&&i>=pre)ans=(ans+dfs(pos-,state,limit&&i==up,i))%MOD;//取模!!!
}
if(!limit&&~pre)f[pos][state][pre]=ans;//记忆化:当前状态和pos,state,pre三者都有关系!!!
return ans;
}
char s[maxn];
int main(){
ll T;
scanf("%lld",&T);
memset(f,-,sizeof(f));
while(T--){
scanf("%s",s+);
n=strlen(s+);
for(int i=;i<=n;i++)a[n-i]=s[i]-'';
printf("%lld\n",dfs(n-,,,-));
}
return ;
}

递推有病啊……细节一大堆,对拍调了一个又一个的错误才AC了,呜呜呜。

主要细节在逐位确定的时候:

1.如果前面递增了,后面枚举数位就不准枚举比前面小的。

2.如果前面递增又递减了,直接退出。

3.如果前面不递增且该位不大于前一位,后面才能取递减的值。

数位DP的逐位递推都是根据高位信息确定低位信息的哦!能干很多事(我选择记忆化搜索QAQ)

#include<cstdio>
#include<cstring>
const int MOD=1e9+,maxn=;
int f[maxn][maxn][],ans,n,a[maxn];
int M(int x){return x>=MOD?x-MOD:x;}
void p(int &x,int y){x=(x+y>=MOD?x+y-MOD:x+y);}
void solve(){
for(int i=;i<n;i++)for(int j=;j<=;j++)p(ans,M(f[i][j][]+f[i][j][]));
for(int j=;j<a[n];j++)p(ans,M(f[n][j][]+f[n][j][]));
bool ok=;
for(int i=n-;i>=;i--){
for(int j=;j<a[i];j++)if(ok||j>=a[i+]){
if(ok&&j<=a[i+])p(ans,M(f[i][j][]+f[i][j][]));
else p(ans,f[i][j][]);
}
if(!ok&&a[i]<a[i+])break;
if(a[i]>a[i+])ok=;
}
}
char s[maxn];
int main(){
int T;scanf("%d",&T);int N=;
for(int j=;j<=;j++)f[][j][]=;
for(int i=;i<=N;i++){
for(int j=;j<=;j++){
for(int k=;k<=;k++){
if(j>k)p(f[i][j][],f[i-][k][]);
else p(f[i][j][],f[i-][k][]);
if(j>=k)p(f[i][j][],f[i-][k][]);
}
}
}
while(T--){
scanf("%s",s+);n=strlen(s+);
for(int i=;i<=n;i++)a[i]=s[n-i+]-'';a[n+]=;
for(int i=;i<=n+;i++)if(a[i]!=){
if(i==n+)n++;
a[i]++;for(int j=i-;j>=;j--)a[j]=;
break;
}
ans=;solve();
printf("%d\n",ans);
}
return ;
}

【HDU】6148 Valley Numer 数位DP的更多相关文章

  1. HDU 6148 Valley Numer (数位DP)

    题意:... 析:好久没写数位DP了,几乎就是不会了.... dp[i][last][s] 表示前 i 位上一位是 last,当前的状态是 s,0表示非上升,1 表示非下降,然后就很简单了,只有 0 ...

  2. 2017"百度之星"程序设计大赛 - 复赛1005&&HDU 6148 Valley Numer【数位dp】

    Valley Numer Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tota ...

  3. HDU 6148 Valley Numer (数位DP)题解

    思路: 只要把status那里写清楚就没什么难度T^T,当然还要考虑前导零! 代码: #include<cstdio> #include<cstring> #include&l ...

  4. HDU 6156 - Palindrome Function [ 数位DP ] | 2017 中国大学生程序设计竞赛 - 网络选拔赛

    普通的数位DP计算回文串个数 /* HDU 6156 - Palindrome Function [ 数位DP ] | 2017 中国大学生程序设计竞赛 - 网络选拔赛 2-36进制下回文串个数 */ ...

  5. hdu 5898 odd-even number 数位DP

    传送门:hdu 5898 odd-even number 思路:数位DP,套着数位DP的模板搞一发就可以了不过要注意前导0的处理,dp[pos][pre][status][ze] pos:当前处理的位 ...

  6. hdu 5106 Bits Problem(数位dp)

    题目链接:hdu 5106 Bits Problem 题目大意:给定n和r,要求算出[0,r)之间全部n-onebit数的和. 解题思路:数位dp,一个ct表示个数,dp表示和,然后就剩下普通的数位d ...

  7. HDU 2089 - 不要62 - [数位DP][入门题]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089 Time Limit: 1000/1000 MS (Java/Others) Memory Li ...

  8. HDU 5179 beautiful number 数位dp

    题目链接: hdu: http://acm.hdu.edu.cn/showproblem.php?pid=5179 bc(中文): http://bestcoder.hdu.edu.cn/contes ...

  9. [hdu 2089] 不要62 数位dp|dfs 入门

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089 题意:求[n, m]区间内不含4和62的数字个数. 这题有两种思路,直接数位dp和dfs 数位d ...

随机推荐

  1. tabales1.10版参数详解

    //@translator codepiano //@blog codepiano //@email codepiano.li@gmail.com //尝试着翻译了一下,难免有错误的地方,欢迎发邮件告 ...

  2. java线程安全— synchronized和volatile

    java线程安全— synchronized和volatile package threadsafe; public class TranditionalThreadSynchronized { pu ...

  3. 将MathType公式转换为LaTex格式

    LaTex编辑公式不够直观,常常会因为结构复杂导致数据或者符号出错,使用MathType编辑公式后再直接转换成LaTex代码可以避免这个问题. 一.首先在MathType中编辑公式 二.然后点击参数— ...

  4. lintcode-148-颜色分类

    148-颜色分类 给定一个包含红,白,蓝且长度为 n 的数组,将数组元素进行分类使相同颜色的元素相邻,并按照红.白.蓝的顺序进行排序. 我们可以使用整数 0,1 和 2 分别代表红,白,蓝. 注意事项 ...

  5. LintCode-112.删除排序链表中的重复元素

    删除排序链表中的重复元素 给定一个排序链表,删除所有重复的元素每个元素只留下一个. 样例 给出 1->1->2->null,返回 1->2->null 给出 1-> ...

  6. JDK源码分析 – ArrayList

    ArrayList类的申明 ArrayList是一个支持泛型的,底层通过数组实现的一个可以存任意类型的数据结构,源码中的定义如下: public class ArrayList<E> ex ...

  7. 3DMAX2016破解教程

    首先,断网. 然后,下载3DMAX2016注册机. 然后,打开已经安装的3DMAX2016,会出现下图,点击激活按钮. 之后,以管理员身份打开3DMAX2016注册机,把申请号复制到注册机里面的请求码 ...

  8. C# 7.0 新特性

    先列一下相关的语法: 1.out-variables(Out变量) 2.Tuples(元组) 3.Pattern Matching(匹配模式) 4.ref locals and returns (局部 ...

  9. arp hook

    最近疯狂的研究Linux的种种功能,也颇有心得,这里讲述一下Linux下的Net的Hook,使用net的Hook可以实现很多很多非常底层的功能,比如过滤报文,做防火墙,做代理等等. Now,Let's ...

  10. Delphi 的绘图功能[8] - TextOut、TextWidth、TextHeight

    unit Unit1; interface uses   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, For ...