【算法】数位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. 《剑指offer》---顺时针打印矩阵

    本文算法使用python3实现 1. 问题1 1.1 题目描述:   输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 ...

  2. lintcode-15-全排列

    全排列 给定一个数字列表,返回其所有可能的排列. 注意事项 你可以假设没有重复数字. 样例 给出一个列表[1,2,3],其全排列为: [ [1,2,3], [1,3,2], [2,1,3], [2,3 ...

  3. Jmeter系列-webdriver代码范例

    范例 WDS.sampleResult.sampleStart() try{ //打开博客首页 WDS.browser.get('http://xqtesting.blog.51cto.com') / ...

  4. C# 知识回顾 - 表达式树 Expression Trees

    C# 知识回顾 - 表达式树 Expression Trees 目录 简介 Lambda 表达式创建表达式树 API 创建表达式树 解析表达式树 表达式树的永久性 编译表达式树 执行表达式树 修改表达 ...

  5. springMVC视图有哪些?-009

    html,json,pdf等. springMVC 使用ViewResolver来根据controller中返回的view名关联到具体的view对象. 使用view对象渲染返回值以生成最终的视图,比如 ...

  6. python dict 字典

    字典是通过hash表的原理实现的,每个元素都是一个键值对,通过元素的键计算出一个唯一的哈希值,这个hash值决定了元素的地址,因此为了保证元素地址不一样,必须保证每个元素的键和对应的hash值是完全不 ...

  7. Linux面试题汇总答案(转)

    转自:小女生的Linux技术~~~Linux面试题汇总答案~~ 一.填空题:1. 在Linux系统中,以 文件 方式访问设备 .2. Linux内核引导时,从文件 /etc/fstab 中读取要加载的 ...

  8. 总结 java 学习

    想着想把以前学的java学习笔记整理下发上来,慢慢整理吧.

  9. Delphi实现在数据库中存取图像

    向窗体上添加一个TListBox组件.一个TImage组件和一个TTable组件,设计完成的主界面如图1所示. 图1 主界面 本系统中需要设计一个新的基于Paradox 7的数据库Image.db,图 ...

  10. bzoj 1877: [SDOI2009]晨跑 (网络流)

    明显拆点费用流: type arr=record toward,next,cap,cost:longint; end; const mm=<<; maxn=; maxm=; var edg ...