数位dp,适用于解决一类求x~y之间有多少个符合要求的数或者其他。

例题

题目描述

杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众。

不吉利的数字为所有含有4或62的号码。例如:

62315 73418 88914

都属于不吉利号码。但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列。

你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多少辆新的士车上牌照了。

输入输出格式

输入的都是整数对A、B(0<A≤B<10^9),如果遇到都是0的整数对,则输入结束。

数据规模

20% 的数据,满足 1≤A≤B≤10^6;

100%的数据,满足 1≤A≤B≤2×10^9。

解法

solve(x)求0~x中符合要求的数有几个;那么答案显然就是solve(b)-solve(n-1)

那么如何solve呢?用记忆化搜索(不用搜索而用普通dp也行,但要麻烦一点)

我们考虑从高位往低位枚举:

  • 如果前面的所有位都“取到顶了”,那么下一位只能取0这一位:比如4375前两位取了43,那么下一位只能取0这一位,也就是0~7

  • 否则,下一位可以取0~9

我们使用flag来表示前几位有没有“取到顶”

f[l][lst]表示的是整个长度为l的数的前面一位是lst的数有多少个。比如f[3][5]表示的就是形如5 ___ ___ ___的数有多少个(注意:不是形如5 ___ ___!)

需要注意的是,只能在flag=0的情况下才能记忆化,因为flag=0时后面是可以取满的;flag=1时后面取不满,而且上限是不定的。

具体实现详见注释。

#include<bits/stdc++.h>
using namespace std;
if(!flag&&f[l][lst]!=-1) return f[l][lst];//记忆化
int u=flag?d[l]:9,anstmp=0;
for(int i=0;i<=u;i++)
if(i!=4&&!(lst==6&&i==2)) //这一位4或者前一位是6这一位是2(也就是组成62)是不行的。
anstmp+=dfs(l-1,i,flag&&i==u);
return flag?anstmp:f[l][lst]=anstmp;//只有flag=0时才能记忆化!
}
inline int solve(int k)
{
cnt=0;
while(k)
{
d[++cnt]=k%10;
k/=10;
}//先将当前的数一位一位拆开
return dfs(cnt,0,1);
}
int main()
{
memset(f,-1,sizeof(f));
while(scanf("%d %d",&n,&m)!=EOF)
{
if(n==m&&n==0) break;
printf("%d\n",solve(m)-solve(n-1));
}
return 0;
}

P2602 [ZJOI2010]数字计数

题目描述

给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码 (digit) 各出现了多少次。

输入格式

仅包含一行两个整数 a,b,含义如上所述。

输出格式

包含一行 10个整数,分别表示 0∼9在[a,b]中出现了多少次。

数据规模

30%的数据中,1≤a≤b≤10^6;

100%的数据中,1≤a≤b≤10^12。

实现

ans[0~9]表示题目的答案。

f[l][lst][11]:f[l][lst][09]表示09各有多少个,f[l][lst][10]表示有几个数

f[l][lst][10]很好算,f[l][lst][0~9]直接算不好算,我们采取在dfs前和dfs后的ans数组做差的方法求出。

dfs中的tstep是调试用的,不用管;dfs中的t是表示加或者减的,因为是0m的答案**减去**0n-1的答案,所以求0m时t=1,0n-1时t=-1

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,m,cnt=0,d[1005],f[1005][1005][11],k,b,ans[1005],bf[1005];
ll dfs(ll l,ll lst,bool flag,bool flagg,ll t,ll tstep)
{
if(l==0) return 1;
if(!flag&&!flagg&&f[l][lst][10]!=-1)
{
for(ll i=0;i<=9;i++) ans[i]+=f[l][lst][i]*t;
return f[l][lst][10];
}
ll u=(flag?d[l]:9),anstmp=0;
for(int i=0;i<=9;i++) bf[i]=ans[i];
for(ll i=0;i<=u;i++)
{
ll tttmp=dfs(l-1,i,flag&&i==u,flagg&&i==0,t,tstep+1);
if(i!=0||!flagg)
{
ans[i]+=tttmp*t;
anstmp+=tttmp;
}
}
if(!flag&&!flagg) {for(int i=0;i<=9;i++) {f[l][lst][i]=abs(ans[i]-bf[i]);}}
return (flag||flagg)?anstmp:f[l][lst][10]=anstmp;
}
inline ll solve(ll k,ll t)
{
cnt=0;
while(k)
{
d[++cnt]=k%10;
k/=10;
}
return dfs(cnt,0,1,1,t,0);
}
int main()
{
memset(f,-1,sizeof(f));
scanf("%lld %lld",&n,&m);
solve(m,1);
solve(n-1,-1);
for(ll i=0;i<=8;i++) printf("%lld ",ans[i]);
printf("%lld",ans[9]);
return 0;
}

数位dp详解&&LG P2602 [ZJOI2010]数字计数的更多相关文章

  1. 洛谷P2602 [ZJOI2010]数字计数 题解 数位DP

    题目链接:https://www.luogu.com.cn/problem/P2602 题目大意: 计算区间 \([L,R]\) 范围内 \(0 \sim 9\) 各出现了多少次? 解题思路: 使用 ...

  2. 数位DP 详解

    序 天堂在左,战士向右 引言 数位DP在竞赛中的出现几率极低,但是如果不会数位DP,一旦考到就只能暴力骗分. 以下是数位DP详解,涉及到的例题有: [HDU2089]不要62 [HDU3652]B-n ...

  3. P2602 [ZJOI2010]数字计数&P1239 计数器&P4999 烦人的数学作业

    P2602 [ZJOI2010]数字计数 题解 DFS 恶心的数位DP 对于这道题,我们可以一个数字一个数字的求 也就是分别统计区间 [ L , R ] 内部数字 i 出现的次数 (0<=i&l ...

  4. P2602 [ZJOI2010]数字计数(递推)

    P2602 [ZJOI2010]数字计数 思路: 首先考虑含有前导0的情况,可以发现在相同的\(i\)位数中,每个数的出现次数都是相等的.所以我们可以设\(f(i)\)为\(i\)位数每个数的出现次数 ...

  5. Luogu P2602 [ZJOI2010]数字计数 数位DP

    很久以前就...但是一直咕咕咕 思路:数位$DP$ 提交:1次 题解:见代码 #include<cstdio> #include<iostream> #include<c ...

  6. 洛谷P2602 [ZJOI2010]数字计数(数位dp)

    数字计数 题目传送门 解题思路 用\(dp[i][j][k]\)来表示长度为\(i\)且以\(j\)为开头的数里\(k\)出现的次数. 则转移方程式为:\(dp[i][j][k] += \sum_{t ...

  7. 动态规划晋级——HDU 3555 Bomb【数位DP详解】

    转载请注明出处:http://blog.csdn.net/a1dark 分析:初学数位DP完全搞不懂.很多时候都是自己花大量时间去找规律.记得上次网络赛有道数位DP.硬是找规律给A了.那时候完全不知数 ...

  8. 数位DP详解

    算法使用范围 在一个区间里面求有多少个满足题目所给的约束条件的数,约束条件必须与数自身的属性有关 下面用kuangbin数位dp的题来介绍 例题  不要62 题意:在一个区间里面求出有多少个不含4和6 ...

  9. P2602 [ZJOI2010]数字计数

    https://www.luogu.org/problemnew/show/P2602 数位dp #include <bits/stdc++.h> using namespace std; ...

随机推荐

  1. selenium-爬取小说

    selenium-爬取小说 1 import requests 2 from bs4 import BeautifulSoup 3 import sys 4 from selenium import ...

  2. python_bisect模块的使用

    这个模块只有几个函数, 一旦决定使用二分搜索时,立马要想到使用这个模块 import bisect L = [1,3,3,6,8,12,15] x = 3 x_insert_point = bisec ...

  3. AVL平衡树(非指针实现)

    看了网上三四篇博客,学习了AVL树维护平衡的方式.但感觉他们给出的代码都有一点瑕疵或者遗漏,懂得了思想之后,花了一些时间把他们几篇的长处结合起来,没有使用指针,实现了一下.每个小逻辑功能都抽象成了函数 ...

  4. AGC033D Complexity

    题意 给出一个\(n*m\)的\(0,1\)矩阵,若一个矩阵中的所有元素都相同,则这个矩阵的代价为\(0\),如果不是则选择一种将它分成两个子矩阵的方案,代价为所有方案中(两个子矩阵的代价的较大值+\ ...

  5. 预处理、const、static与sizeof-为什么不把所有的函数都定义成内联函数

    1:内联是以代码膨胀(复制)为代价的,仅仅省去了函数调用的开销,从而提高函数的执行效率.如果执行函数体内代码的时间相比于函数调用的开销较大,那么效率的收获会很小.另一方面,每一处内联函数的调用都要复制 ...

  6. Linux设备驱动程序 之 原子操作

    原子整数操作 当共享资源是一个简单的整数值时,可以使用内核提供的一种原子的整数类型,称为atomic_t,定义在<linux/types.h>中,操作定义在<linux/atomic ...

  7. Netfilter 之 连接跟踪初始化

    基础参数初始化 nf_conntrack_init_start函数完成连接跟踪基础参数的初始化,包括了hash,slab,扩展项,GC任务等: int nf_conntrack_init_start( ...

  8. Java第00周作业

    ---恢复内容开始--- 1.你对专业的认识和期望是什么? 徐老师说过,C语言是很多语言的基础,学好C语言,将来接触的不论是面向对象还是面向过程的语言都能沉下心,能轻松解决面临的问题,处理棘手的麻烦, ...

  9. Bootstrap视频教程

    一.全局CSS样式 0.课件 001.概览_栅格系统 2.排版和代码 3.表格和按钮 4.表单 5.图片 6.辅助类 7.响应式工具 二.组件 8.图标_下拉菜单_按钮组 9.输入框组 10.导航 1 ...

  10. laravel-5.6路由命名

    1.第一种:通过route路由中的as关键字来实现 1 Route::get('api/user',['as'='web.user'],'messageController@userInformati ...