初探数位dp
数位dp有着很明显的特点,一般来说是给定区间[l,r]求满足某种条件区间中的数有多少个
朴素解法一般是O(n)的而n往往很大(10^8起步)
这时候我们就要想办法优化,于是就有了数位dp
数位有两个基本的原则
对于区间数的个数,我们转化为前缀和做(即ans=sum(r)-sum(l-1))
逐位确定
我认为第二条很关键,可以说是数位dp的精髓
一般来说数位dp分两步
打表 形如f[i,j]到有i位且最高位为j的满足条件的个数
统计前缀和
统计前缀和我们需要用到一个非常重要的结论
对于任意一个小于n的数,从高位到低位,必然出现了某一位小于n的那一位
这样我们就可以不受n的限制,用数位开始处理
以bzoj1026这道经典的题目为例
- var f:array[..,..] of longint;
- d:array[..] of longint;
- l,r,t,i,j,k:longint;
- function get(n:longint):longint;
- var i,s,x,j:longint;
- begin
- if (n>=) and (n<=) then exit(n);
- fillchar(d,sizeof(d),);
- s:=;
- while n<> do
- begin
- inc(s);
- d[s]:=n mod ;
- n:=n div ;
- end;
- get:=;
- for i:= to s- do //统计位数小于n的位数的满足条件的数目
- for j:= to do
- get:=get+f[i,j];
- //注意这里是不能直接加前导为0的数组,因为我们在计算前导为0的时候,实际上舍掉了后一位为0~的情况
- for i:=s downto do //从高到低逐位统计位数为n的位数且小于n的满足条件的个数
- begin
- if i<> then x:=d[i]- else x:=d[i]; //小细节,注意n本身也可能是
- for j:= to x do //当前位小于n的这位的满足条件的数
- begin
- if (i=s) and (j=) then continue;
- if (s=i) or (abs(j-d[i+])>=) then
- get:=get+f[i,j];
- end;
- if (s<>i) and (abs(d[i+]-d[i])<) then break; //如果逐位统计n本身出现了不满足的情况,那显然要直接退出
- end;
- end;
- begin
- readln(l,r);
- t:=trunc(ln(r)/ln())+;
- for i:= to do //题目的特殊要求
- f[,i]:=;
- for i:= to t do //计算f[i,j]
- begin
- for j:= to do //注意要包含前导为0的状况
- for k:= to do
- if abs(j-k)>= then
- f[i,j]:=f[i,j]+f[i-,k];
- end;
- writeln(get(r)-get(l-));
- end.
bzoj1026
(话说我第一次拍这道题花了3h,实在太渣……)
当然我们也不能拘泥于这种套路,我觉得
当表打了没什么用的时候我们可以直接逐位计算,如poj3286(统计0的个数)
这里我们讨论,每一位对0的贡献度
- var d:array[..] of int64;
- i:longint;
- l,r:int64;
- function count(n:int64):int64;
- var i,t:longint;
- x,y:int64;
- begin
- for i:= to do
- if (n<d[i]) then break;
- t:=i-;
- count:=;
- for i:= to t do
- begin
- x:=n div d[i]; //当前位前面所组成的数
- y:=n mod d[i-]; //当前位后面所组成的数
- if (n div d[i-] mod )= then //当前位
- count:=count+d[i-]*(x-)+y+
- //如果是x0y的情况,是第k位时,我们分2种情况讨论
- 当小于n的数是p0q的,p∈[,x-],那么这个位上的0可以贡献(x-)*^(k-)
- 当这个小于等于n的数是x0q, q∈[,y]那么这个位上的0可以贡献y+
- else count:=count+d[i-]*x;
- //如果当前位不是0,那显然比n小的数中肯定存在当前位为0的;
- 设数为p0q, p∈[,x], q∈[,^(k-)-] 因为当前位已经小于则显然可以贡献x*^(k-)
- end;
- end;
- begin
- d[]:=;
- for i:= to do
- d[i]:=d[i-]*;
- readln(l,r);
- while (l<>-) do
- begin
- if l= then writeln(count(r))
- else writeln(count(r)-count(l-));
- readln(l,r);
- end;
- end.
poj3286
数位dp需要大量的思考,有时候看起来对的实际上是错的
但由于这种题目暴力,数据都非常好弄
所以一定要孜孜不倦的对拍,恩恩
初探数位dp的更多相关文章
- 数位dp入门 hdu2089 不要62
数位dp入门 hdu2089 不要62 题意: 给定一个区间[n,m] (0< n ≤ m<1000000),找出不含4和'62'的数的个数 (ps:开始以为直接暴力可以..貌似可以,但是 ...
- [bzoj1833][ZJOI2010]count 数字计数——数位dp
题目: (传送门)[http://www.lydsy.com/JudgeOnline/problem.php?id=1833] 题解: 第一次接触数位dp,真的是恶心. 首先翻阅了很多很多一维dp,因 ...
- 数位dp初探
我这种蒟蒻就一直不会写数位dp.. 于是开了个坑.. 1833: [ZJOI2010]count 数字计数 这道被KPM大爷说是入门题..嗯似乎找找规律然后减掉0的情况后乱搞就可以了..(但是还是写了 ...
- 数位类统计问题--数位DP
有一类与数位有关的区间统计问题.这类问题往往具有比较浓厚的数学味道,无法暴力求解,需要在数位上进行递推等操作.这类问题往往需要一些预处理,这就用到了数位DP. 本文地址:http://www.cnbl ...
- 动态规划——数位dp
通过先前在<动态规划——背包问题>中关于动态规划的初探,我们其实可以看到,动态规划其实不是像凸包.扩展欧几里得等是具体的算法,而是一种在解决问题中决策的思想.在不同的题目中,我们都需要根据 ...
- 【BZOJ1662】[Usaco2006 Nov]Round Numbers 圆环数 数位DP
[BZOJ1662][Usaco2006 Nov]Round Numbers 圆环数 Description 正如你所知,奶牛们没有手指以至于不能玩"石头剪刀布"来任意地决定例如谁 ...
- bzoj1026数位dp
基础的数位dp 但是ce了一发,(abs难道不是cmath里的吗?改成bits/stdc++.h就过了) #include <bits/stdc++.h> using namespace ...
- uva12063数位dp
辣鸡军训毁我青春!!! 因为在军训,导致很长时间都只能看书yy题目,而不能溜到机房鏼题 于是在猫大的帮助下我发现这道习题是数位dp 然后想起之前讲dp的时候一直在补作业所以没怎么写,然后就试了试 果然 ...
- HDU2089 不要62[数位DP]
不要62 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
随机推荐
- Android Google购买PHP服务器端验证(订阅购买和一次性购买)
一.订阅购买验证 android端采用google service account进行校验 1.打开https://cloud.google.com/console创建一个project: 2.打开p ...
- [Linux]学习笔记(2)
本节主要学习: whoami who am i who w users tty 6个命令的用法. (1)whoami whoami用于查询当前是以哪个用户登录Linux系统: [root@linuxf ...
- a标签点击后的虚线框问题
以前一直用的方法都是: a {outline: none;star:expression(this.onFocus=this.blur());} 后来发现有瑕疵,不完美.体现在页面调用JS动作比较频繁 ...
- C# 学习之旅(3) --- 会说话的简易计算器
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- C语言数据结构之栈:中缀表达式的计算
*注:本人技术不咋的,就是拿代码出来和大家看看,代码漏洞百出,完全没有优化,主要看气质,是吧 学了数据结构——栈,当然少不了习题.习题中最难的也是最有意思的就是这个中缀表达式的计算了(可以算+-*/和 ...
- Nginx配置文件变量大全
$args # 这个变量等于请求行中的参数. $binary_remote_addr # 远程地址的二进制表示 $body_bytes_sent # 已发送的消息体字节数 $content_lengt ...
- iOS实例下载:使用腾讯的SDK将新浪微薄嵌入到应用中
最近在做应用中添加SNS分享功能,只需要分享功能,腾讯的SDK和Demo还是挺直观的,看了下基本上就能用了,而新浪的Oauth认证看了个例子是跳出程序到Web上去认证的,体验很不好.不过Oauth认证 ...
- C# Windows - TextBox 控件
.NET Framework内置了两个基本控件来提取用户输入的文本: TextBox和RichTextBox.这两个控件都派生于基类TextBoxBase,而TextBoxBase派生于Control ...
- jQuery DataTables Plugin Meets C#
Over the weekend, I was doing some work on the internal CMS we use over at eagleenvision.net and I w ...
- ExtJs gridPanel Column 时间格式化
var panel = new Ext.container.Viewport({ items: { xtype: 'gridpanel', id: 'gridPanel', store: store, ...