数位dp详解&&LG P2602 [ZJOI2010]数字计数
数位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]数字计数的更多相关文章
- 洛谷P2602 [ZJOI2010]数字计数 题解 数位DP
题目链接:https://www.luogu.com.cn/problem/P2602 题目大意: 计算区间 \([L,R]\) 范围内 \(0 \sim 9\) 各出现了多少次? 解题思路: 使用 ...
- 数位DP 详解
序 天堂在左,战士向右 引言 数位DP在竞赛中的出现几率极低,但是如果不会数位DP,一旦考到就只能暴力骗分. 以下是数位DP详解,涉及到的例题有: [HDU2089]不要62 [HDU3652]B-n ...
- P2602 [ZJOI2010]数字计数&P1239 计数器&P4999 烦人的数学作业
P2602 [ZJOI2010]数字计数 题解 DFS 恶心的数位DP 对于这道题,我们可以一个数字一个数字的求 也就是分别统计区间 [ L , R ] 内部数字 i 出现的次数 (0<=i&l ...
- P2602 [ZJOI2010]数字计数(递推)
P2602 [ZJOI2010]数字计数 思路: 首先考虑含有前导0的情况,可以发现在相同的\(i\)位数中,每个数的出现次数都是相等的.所以我们可以设\(f(i)\)为\(i\)位数每个数的出现次数 ...
- Luogu P2602 [ZJOI2010]数字计数 数位DP
很久以前就...但是一直咕咕咕 思路:数位$DP$ 提交:1次 题解:见代码 #include<cstdio> #include<iostream> #include<c ...
- 洛谷P2602 [ZJOI2010]数字计数(数位dp)
数字计数 题目传送门 解题思路 用\(dp[i][j][k]\)来表示长度为\(i\)且以\(j\)为开头的数里\(k\)出现的次数. 则转移方程式为:\(dp[i][j][k] += \sum_{t ...
- 动态规划晋级——HDU 3555 Bomb【数位DP详解】
转载请注明出处:http://blog.csdn.net/a1dark 分析:初学数位DP完全搞不懂.很多时候都是自己花大量时间去找规律.记得上次网络赛有道数位DP.硬是找规律给A了.那时候完全不知数 ...
- 数位DP详解
算法使用范围 在一个区间里面求有多少个满足题目所给的约束条件的数,约束条件必须与数自身的属性有关 下面用kuangbin数位dp的题来介绍 例题 不要62 题意:在一个区间里面求出有多少个不含4和6 ...
- P2602 [ZJOI2010]数字计数
https://www.luogu.org/problemnew/show/P2602 数位dp #include <bits/stdc++.h> using namespace std; ...
随机推荐
- delphi将两个Strlist合并,求交集 (保留相同的)
Function StrList_Join(StrListA,StrListB:String):String; //将两个Strlist合并,求交集 (保留相同的) var SListA,SListB ...
- 转:后置处理器JSON Extractor 提取json的多个值
json串 []表示对象组成的数组,{}表示对象. 对象里包含多个 "属性":属性值.属性值可以是值,或数组,或对象. JSON Extractor使用json path表达式匹配 ...
- Little Prince
You know — one loves the sunset, when one is so sad... 你知道的—当一个人情绪低落的时候,他会格外喜欢看日落...... If someone l ...
- python 编写排列组合
python在编写排列组合是会用到 itertools 模块 排列 import itertools mylist = list(itertools.permutations([)) # 全排列 p ...
- epoll反应堆
/* * epoll基于非阻塞I/O事件驱动 */ #include <stdio.h> #include <sys/socket.h> #include <sys/ep ...
- vue 源码解析computed
计算属性 VS 侦听属性 Vue 的组件对象支持了计算属性 computed 和侦听属性 watch 2 个选项,很多同学不了解什么时候该用 computed 什么时候该用 watch.先不回答这个问 ...
- ACM之路(17)—— 博弈论
博弈论这方面网上资料庞大,我觉得我不可能写的比他们好,就转载一下我觉得写的不错的博客好了. 首先是三大博弈:巴什博奕,威佐夫博奕,尼姆博奕.博客:三大基本博弈. 然后是强大的sg函数和sg定理:SG. ...
- 2016 Multi-University Training Contest 1 部分题解
第一场多校,出了一题,,没有挂零还算欣慰. 1001,求最小生成树和,确定了最小生成树后任意两点间的距离的最小数学期望.当时就有点矛盾,为什么是求最小的数学期望以及为什么题目给了每条边都不相等的条件. ...
- springboot+shiro 跨域解决(OPTIONS)
拦截器判断 拦截器截取到请求先进行判断,如果是OPTIONS请求的话,则放行 import com.alibaba.fastjson.JSON; import com.zp.demo.util.Jwt ...
- React Native 日常报错
在学习React.js 或 React Native 过程中,有时看着别人的框架或代码,但总是会出现错误,因为React或之中用到的一些包经常更新,有些代码或教程就显得过旧了. 一.日常报错 'con ...