数位DP 学习笔记

板子题

出处
escription
蒟蒻hzwer NOIP2014惨跪,他依稀记得他的准考证号是37,现在hzwer又将要面临一场比赛,他希望准考证号不出现37(连续),同时他又十分讨厌4,所以也不希望4出现在准考证号中。。。现在他想知道在A和B之间有多少合法的准考证号
Input
包含两个整数,A B
Output
一个整数。
Sample Input
「输入样例一」

1 10

「输入样例二」

25 50

Sample Output
「输出样例一」

9

「输出样例二」

14

「数据规模和约定」
20% 的数据,满足 1AB1000000
100% 的数据,满足 1AB2000000000

算法解析

因为不要求输出路径,而且不能贪心,那么考虑DP。
但是我们发现DP的状态很难设计,这里就要用到数位DP来解决这个问题了。
数位DP把一个数字拆开成若干位,如下图,把每一位当做一个节点,也就是说,把每一位当做一个独立的节点,然后设计方程式。一般方程状态是位数和当前位的状态。

数位DP一般有两种计算方法,一种是记忆化搜索(递归),另一种是递推。因为一般给出条件的时候不是位数,而是具体的一个数字。
我们发现,如果要用记搜的话,就要从高到低进行扫描;递推则从低到高。

题目解析

f(x,y,op) 表示从高到低第 x 位,前一位为 y ,如果 op=1 则之前的数字取的是最大值,否则不是的答案。
递推式显然。
算法复杂度为 Θ(10N)N 为位数, 10 就是指总共每位有 10 个数字。

代码

(此代码防抄袭)

#include<cstdio>
#include<cstring>
#define maxn 39
using namespace std;
#define debug
typedef int Type;
inline Type read(){
Type sum=0;
int flag=0;
char c=getchar();
while((c<'0'||c>'9')&&c!='-') c=getchar();
if(c=='-') c=getchar(),flag=1;
while('0'<=c&&c<='9'){
sum=(sum<<1)+(sum<<3)+(c^48);
c=getchar();
}
if(flag) return -sum;
return sum;
}
int from,to;
int tmp[maxn],n;
int dp[maxn][maxn][2];
void swap(int &x,int &y){ x^=y^=x^=y; }
int f(int x,int y,int op){
if(dp[x][y][op]) return dp[x][y][op];
if(x==n+1) return dp[x][y][op]=1;
int cnt=0;
if(op){
for(int i=0;i<=tmp[x]-1;i++)
if(i!=4&&(y!=3||i!=7))
cnt+=f(x+1,i,0);
if(tmp[x]!=4&&(y!=3||tmp[x]!=7))
cnt+=f(x+1,tmp[x],1);
}
else{
for(int i=0;i<=9;i++)
if(i!=4&&(y!=3||i!=7))
cnt+=f(x+1,i,0);
}
return dp[x][y][op]=cnt;
}
int getans(int x){
n=0;
while(x){
tmp[++n]=x%10;
x/=10;
}
memset(dp,0,sizeof(dp));
for(int i=1;i<=(n>>1);i++)
swap(tmp[i],tmp[n-i+1]);
return f(1,tmp[1],1);
}
int main(){
freopen("1.in","r",stdin);
freopen("my.out","w",stdout);
#ifdef debug
to=read(); printf("%d",getans(to));
#else
from=read(); to=read();
printf("%d",getans(to)-getans(from-1));
#endif
return 0;
}

推荐练习

[ZJOI2010]数字计数
[SCOI2009] windy 数
又可以水很多蓝题和紫题了

posted @   jiangtaizhe001  阅读(46)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示