数位DP:不要62(第一道题,主要是弄懂数位DP是啥意思)
2013-11-27 16:38
281 查看
A - 不要62
Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d
& %I64u
Submit Status
Description
杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer)。
杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众。
不吉利的数字为所有含有4或62的号码。例如:
62315 73418 88914
都属于不吉利号码。但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列。
你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多少辆新的士车上牌照了。
Input
输入的都是整数对n、m(0<n≤m<1000000),如果遇到都是0的整数对,则输入结束。
Output
对于每个整数对,输出一个不含有不吉利数字的统计个数,该数值占一行位置。
Sample Input
Sample Output
这题搞了两天了……才明白数位DP是什么意思,而且该怎么解……模板每一句话的意思与作用……
下面是数位通用模板的代码与解释:
Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d
& %I64u
Submit Status
Description
杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer)。
杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众。
不吉利的数字为所有含有4或62的号码。例如:
62315 73418 88914
都属于不吉利号码。但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列。
你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多少辆新的士车上牌照了。
Input
输入的都是整数对n、m(0<n≤m<1000000),如果遇到都是0的整数对,则输入结束。
Output
对于每个整数对,输出一个不含有不吉利数字的统计个数,该数值占一行位置。
Sample Input
1 100 0 0
Sample Output
80
这题搞了两天了……才明白数位DP是什么意思,而且该怎么解……模板每一句话的意思与作用……
下面是数位通用模板的代码与解释:
int dfs(int i, int s, bool e) { if (i==-1) return s==target_s; if (!e && ~f[i][s]) return f[i][s]; int res = 0; int u = e?num[i]:9; for (int d = first?1:0; d <= u; ++d) res += dfs(i-1, new_s(s, d), e&&d==u); return e?res:f[i][s]=res; }f为记忆化数组; i为当前处理串的第i位(权重表示法,也即后面剩下i+1位待填数); s为之前数字的状态(如果要求后面的数满足什么状态,也可以再记一个目标状态t之类,for的时候枚举下t); 在这题中s==0时表示即不含有6和4的,s==1时表示含有6不含有4的,s==2时表示含有4或者62的 e表示之前的数是否是上界的前缀(即后面的数能否任意填)。
#include <iostream> #include <map> #include <deque> #include <queue> #include <stack> #include <string> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <map> #include <set> using namespace std; int n,m,f[10][10],num[10]; int dfs(int i,int s,bool e) //i为第几个数,s为每个数的状态,在本题中共设0,1,2三个状态,上面已经说过 { if(i==-1) return 1; //因为4和62的情况continue掉了,所以返回s==0||s==1肯定是真的,真就是返回1 if(!e&&f[i][s]!=-1) return f[i][s]; //记忆哪个数时前面已经有多少个符合的数,直接返回就行 int res=0; int u=e?num[i]:9; //下一个数可以取多少 for(int d=0; d<=u; ++d) //有时候d不得取0,那么判断一下看看得不得取 { if(s==6&&d==2) continue; else if(d==4) continue; else res+=dfs(i-1,d,e&&d==u); } return e?res:f[i][s]=res; } int open(int x) { int k=0; while(x) { num[k++]=x%10; //从后往前取每位的数存入数组中 x/=10; } return k; } int gets(int n) { int mm=open(n); return dfs(mm-1,0,1); } void solve() { printf("%d\n",(gets(m)-gets(n-1))); } int main() { memset(f,-1,sizeof(f)); while(scanf("%d%d",&n,&m)&&(n||m)) solve(); return 0; }
相关文章推荐
- python 多线程
- 根据IP获取省市 .
- 【Android Developers Training】 9. 覆盖于布局之上的Action Bar
- GridView实现自动编号;GridView实现自定义时间货币等字符串格式;GridView实现用“...”代替超长字符串;GridView一般换行与强制换行;GridView显示隐藏某一列;
- centos6 下安装星际译王stardict3.0
- C#事件(event)解析
- Lucene使用IKAnalyzer分词实例 及 IKAnalyzer扩展词库
- richTextBox设置选中的字体属性
- 实战BULK COLLECT(成批聚合类型)和数组集合type类型is table of 表%rowtype index by binary_integer
- ROS on ARM pcduino
- 使用libxml2创建和解析xml文件
- PLSQL 连接不上64位ORACLE数据库解决办法
- SQL SERVER 2005数据库还原的方法
- vmware workstation虚拟机中的虚拟网络简介
- Oracle 动态性能表 v$session & v$process
- ASP.NET三层架构介绍及数据库配置方法
- PHP框架的制作原理
- 二进制数反转
- php中利用正则去掉中文全角空格
- C#中的枚举类型