数位DP--由一道微软笔试题引起
前天晚上,一位研三的学长突然跑到我们宿舍,问我们一道微软笔试题。给你一个整数n,求出1到n这个区间范围内包含数字0的个数,例如当n=10的时候就只有10包含0,输出1,n=90就输出9。唯一的要求是此题不能用遍历来实现,时间负责度要比O(n)小,要是遍历显然谁都会做。
初看此题,似乎能找到规律,应该是排列组合的思想,下面是我认识的一个学数学的同学提供的思路:
用数学方法看起来应该能够解决,不过并没有尝试。在问了一个ACM大牛后,得到了一个名词“数位DP”,并且发现其实有很多与此类似的题目,都可以用数位DP的方法求解。
下面先给出数位DP的背景:
为了降低时间复杂度,可以借鉴传统DP中状态转换,打表这些思路,得到了数位DP:
F(A,B) = F(B,0)-F(A-1,0)
暴力+存储 = 记忆化搜索
针对上面几种类型的问题,数位DP解决方案如下:(具体可以看http://www.cppblog.com/Yuan/archive/2011/07/15/139299.html)
在这几种类型中,包含49的与微软这道题最为相近,不过要注意的是运算过程中需要把前缀0的情况剔除,最终代码如下:
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
using namespace std;
typedef long long ll;#define mem(a,b) memset(a,b,sizeof(a))const int L = 20, P = 1e9+7;struct RES
{ll all, sum, cnt;RES() {}RES(int i,int j,int k):all(i),sum(j),cnt(k) {}
} dp[L];ll chkmod(ll x,ll p)
{return (x%p+p)%p;
}int d[L], n;RES dfs(int pos, int UP)
{if(pos<0){return RES(0,0,1);}if(!UP && ~dp[pos].all){return dp[pos];}RES ret(0,0,0);int up=UP?d[pos]:9;ret.all += dfs(pos-1, UP&&up==0).all;ret.all %= P;for(int i=1;i<=up;i++) {int nUP = UP&&i==up;for(int j=pos-1;j>=-1;j--) {ll tmp = dfs(j, nUP).sum + dfs(j, nUP).cnt * (pos - 1 - j);tmp %= P;ret.all += tmp;ret.all %= P;ret.sum += tmp;ret.sum %= P;ret.cnt += dfs(j, nUP).cnt;ret.cnt %= P;nUP = nUP && d[j]==0; // !!!}}if(!UP) {dp[pos] = ret;}return ret;
}ll cal(ll x)
{n=0;while(x) {d[n++]=x%10;x/=10;}return dfs(n-1,1).all;
}int main()
{mem(dp,-1);ll n;while(cin>>n) {cout<<cal(n)<<endl;}return 0;
}
数位DP--由一道微软笔试题引起相关推荐
- 一道微软面试题的运算过程解析
这是一道微软的面试题: int func(x) { int countx =0; while(x) { countx ++; x = x&(x-1); } return countx; } 假 ...
- 答与微博前端教主在吃饭时讨论到的一道微软面试题
加引号是因为我不知道是否真是微软面试题.题目是这样的: 有一车在某无限长公路上行驶,其起始位置和单位时间内速度均为有限大整数(正负不确定), 现有一仪器,在每一时间单位内可以探测1次车是否在指定位置, ...
- 一道有趣的微软笔试题
老师d 的物理测验答案在教室里丢失了,今天那个教室上了5 堂课,老师d 上了3 堂,有可 能是a.b.c 三个同学盗窃 已知:1.a 上了两堂课 2.b 上了三堂课 3.c 上了四堂课 4.a.b.c ...
- ios笔试题算法_微软笔试题-Dijkstra算法
Dijkstra算法是典型的算法.Dijkstra算法是很有代表性的算法.Dijkstra一般的表述通常有两种方式,一种用永久和临时标号方式,一种是用OPEN, CLOSE表的方式,这里均采用永久和临 ...
- 博彦科技软件测试工程师一道C笔试题
测试空间旗下大头针出品 前段时间学员去笔试遇到的. 北京博彦科技一道C笔试 分别填入一个语句,完成下面的函数,通过递归计算数组a[100]的前n个数之和. int sum ( int a[],int ...
- 关于虚函数(多态)与继承的一道搜狗笔试题
#include<iostream> using namespace std; /*Name: Copyright: Author: Date: 25/03/13 09:12Descrip ...
- 微软笔试题,机器人消砖块
我比较傻叉,居然忘了用动态规划做,用了递归,各种边界判断,而且数组稍大一点就栈溢出.递归可以剪支,稍微减少一些递归次数.不管怎么样还是贴上自己的傻叉代码吧 #include<iostream&g ...
- 微软笔试题 2013暑期实习笔试题目
2019独角兽企业重金招聘Python工程师标准>>> 1: 有1000瓶水,其中1瓶是有毒的,小老鼠如果喝了有毒的水会在一个星期后死掉,问至少需要多少只小老鼠来做实验,才能够在一星 ...
- 微软笔试题(看到的写答案啊)
int func(int n, int* r) { printf("n=%d *r=%d\n",n,*r);//加了个打印的东西 return n && (*r + ...
最新文章
- Docker桌面不再对企业用户免费,每月订阅费最高21美元,用户直接炸锅了
- 关于h5py的使用及数据封装实例
- SAP CRM Fiori应用My Note的OData调用设计
- html转盘游戏,html5大转盘抽奖实例源码(基于vue.js)
- 英伟达自动驾驶技术:用于自动驾驶汽车的端到端深度学习
- (22)VHDL实现比较器(二位数值)
- matplotlib绘制虚线_[Matplotlib习题]虚线绘图练习
- python numpy库安装winerror5_求问安装numpy+mkl报错FileNotFoundError: [Errno 2] No such fi
- spring源码解析bean定义五ContextNamespaceHandler一
- Python print 语句(Python 2 与 Python 3)
- C++编程练习(14)-------“单例模式”的实现
- js获取image中src属性的方法语句
- 视频防泄密安全解决方案
- c语言程序设计职工信息管理系统,C语言程序设计-职工信息管理系统.doc
- CopyU!v2 已经收录到腾讯软件管家!
- 微信小程序引入 vant UI组件库
- 固态硬盘与普通硬盘有哪些区别?
- Unity3D延迟执行功能脚本
- 域名注册查询批量筛选工具
- 中国房地产泡沫规模巨大将载入历史 面临崩溃风险