【背景】

在10月3日的dp专练中,压轴的第6题是一道数位dp,于是各种懵逼。

为了填上这个留存已久的坑,蒟蒻chty只能开坑数位dp了。

【例题一】[HDU2089]不要62

题目大意:给你一个区间[l,r],求区间内不含4和62的数的个数。

分析:首先  ans[l,r]=ans[0,r]-ans[0,l-1],这样成功将问题转化为了求区间[0,x]的答案,然后减一下即可。

   然后可以预处理出一个f[][]数组,f[i][j]表示表示在i位数中以j开头的满足条件的数的个数,那么显然f[i][j]=sum{f[i-1][k]} (0<=k<=9&&j!=4&&!(j==6&&k==2))

   然后用一个digit[]数组记录当前x从高位到低位的数字,如x=529,则digit[1]=5,digit[2]=2,digit[3]=9

   最后从高到低按位累加答案即可。(这点不明白的可以看我的代码,毕竟有些东西只能意会,无法言传)

 #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<ctime>
using namespace std;
int n,m,digit[],f[][];
inline int read()
{
int x=,f=; char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-; ch=getchar();}
while(isdigit(ch)) {x=x*+ch-''; ch=getchar();}
return x*f;
}
void pre()
{
memset(f,,sizeof(f));
f[][]=;
for(int i=;i<=;i++)
for(int j=;j<=;j++)
for(int k=;k<=;k++)
if(j!=&&!(j==&&k==))
f[i][j]+=f[i-][k];
}
int ask(int x)
{
int len=,ans=;
while(x){digit[++len]=x%;x/=;}
digit[len+]=;
for(int i=len;i;i--)
{
for(int j=;j<digit[i];j++) if(j!=&&!(j==&&digit[i+]==)) ans+=f[i][j];
if(digit[i]==||(digit[i]==&&digit[i+]==)) break;
}
return ans;
}
int main()
{
//freopen("cin.in","r",stdin);
//freopen("cout.out","w",stdout);
pre();
while()
{
n=read(); m=read();
if(n==&&m==) break;
printf("%d\n",ask(m+)-ask(n));
}
return ;
}

【练习一】[bzoj1026]windy数

题目描述:windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,在A和B之间,包括A和B,总共有多少个windy数?

建议这题自己想做法,其实和上面那道题差不多了。

如果你真的wa到受不了,参考代码:http://www.cnblogs.com/chty/p/5981569.html

【练习二】[hdu3555]bomb

题目大意:求给定区间的含有49的数的个数。

分析:我们可以转换一下思维,先求出区间内不含49的数的个数,然后用n减去这个数就行了,这就转化为了练习一的方法。(与网上其他题解不太一样,个人认为这种做法更简单)

 #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
using namespace std;
typedef long long ll;
ll T,digit[],f[][];
inline ll read()
{
ll x=,f=; char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-; ch=getchar();}
while(isdigit(ch)) {x=x*+ch-''; ch=getchar();}
return x*f;
}
void pre()
{
f[][]=;
for(ll i=;i<=;i++)
for(ll j=;j<=;j++)
for(ll k=;k<=;k++)
if(!(j==&&k==)) f[i][j]+=f[i-][k];
}
ll ask(ll x)
{
ll len=,ans=;
while(x) {digit[++len]=x%; x/=;}
digit[len+]=;
for(ll i=;i<len;i++)
for(ll j=;j<=;j++)
ans+=f[i][j];
for(ll i=;i<digit[len];i++) ans+=f[len][i];
for(ll i=len-;i;i--)
{
for(ll j=;j<digit[i];j++) if(!(digit[i+]==&&j==)) ans+=f[i][j];
if(digit[i+]==&&digit[i]==) break;
}
return ans;
}
int main()
{
//freopen("cin.in","r",stdin);
//freopen("cout.out","w",stdout);
T=read(); pre();
while(T--){ll n=read();printf("%I64d\n",n-ask(n+));}
return ;
}

【例题二】[poj3208]Apocalypse Someday

描述 Description
探险队员终于进入了金字塔。通过对古文字的解读, 他们发现,和《圣经》的作者想的一样,古代人认为 666 是属于魔鬼的数。不但如此,只要某数字的十进制表示中 有三个连续的 6,古代人也认为这个是魔鬼的数,比如 666,
1 666, 2 666, 3 666, 6 663, 16 666, 6 660 666 等等,统统是魔 鬼的数。
古代典籍经常用“第 X 大的魔鬼的数”来指代这些数。 这给研究人员带来了极大的不便。为了帮助他们,你需要写一个程序来求出这些魔鬼的数字。

题解详见http://blog.csdn.net/popoqqq/article/details/39319021

用上述方法写这道题的代码如下:

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<algorithm>
using namespace std;
typedef long long ll;
ll T,S,f[][],digit[];
inline ll read()
{
ll x=,f=; char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-; ch=getchar();}
while(isdigit(ch)) {x=x*+ch-''; ch=getchar();}
return x*f;
}
void pre()
{
f[][]=;
for(ll i=;i<=;i++)
{
f[i][]=(f[i-][]+f[i-][]+f[i-][])*;
f[i][]=f[i-][];
f[i][]=f[i-][];
f[i][]=f[i-][]+f[i-][]*;
}
}
int getans(ll x)
{
ll len=,ans=,cnt=;
while(x) {digit[++len]=x%; x/=;}
for(ll i=len,j;i;i--)
{
ll sum;
for(int j=;j<=digit[i];j++)
{
if(cnt==) sum=;
else if(j==) sum=cnt+;
else sum=;
for(ll k=;k>=-sum;k--) ans+=f[i-][k];
}
if(cnt!=) cnt=(digit[i]==?cnt+:);
}
return ans;
}
int main()
{
//freopen("cin.in","r",stdin);
//freopen("cout.out","w",stdout);
T=read(); pre();
while(T--)
{
ll S=read(),l=,r=100000000000ll;
while(l+<r)
{
ll mid=(l+r)/;
if(getans(mid+)>=S) r=mid;
else l=mid;
}
if(getans(r)==S) printf("%I64d\n",l);
else printf("%I64d\n",r);
}
return ;
}

开坑数位dp的更多相关文章

  1. 数位dp踩坑

    前言 数位DP是什么?以前总觉得这个概念很高大上,最近闲的没事,学了一下发现确实挺神奇的. 从一道简单题说起 hdu 2089 "不要62" 一个数字,如果包含'4'或者'62', ...

  2. 【距离GDOI:141天】 滚入数位DP的坑

    作为博客园的第一篇...我都不知道要写什么了 ... 其实今天很没状态,就当吐槽吧... 嗯,被黄神带去写treap+可持久化线段树,然后在可持久化的删除上面跪了两天,真的是一跪不起.我已经连续多久没 ...

  3. # 数位DP入坑

    Hdu 2089 不要62 #include<iostream> #include<cstdio> #include<cmath> #include<cstr ...

  4. 浅谈数位DP

    在了解数位dp之前,先来看一个问题: 例1.求a~b中不包含49的数的个数. 0 < a.b < 2*10^9 注意到n的数据范围非常大,暴力求解是不可能的,考虑dp,如果直接记录下数字, ...

  5. 数位DP入门:(bzoj1833+3209)

    //我是来看文章创建时间的= = 膜拜了一下蔡大神.... 人生第一道自己写的数位DP...好吧以前是看题解然后也不知道为什么就过了的>_< 虽然说现在还是只会裸题= = 数位DP介绍: ...

  6. 数位dp初探

    我这种蒟蒻就一直不会写数位dp.. 于是开了个坑.. 1833: [ZJOI2010]count 数字计数 这道被KPM大爷说是入门题..嗯似乎找找规律然后减掉0的情况后乱搞就可以了..(但是还是写了 ...

  7. 数位dp小练

    最近刷题的同时还得填填坑,说来你们也不信,我还不会数位dp. 照例推几篇博客: 数位DP讲解 数位dp 的简单入门 这两篇博客讲的都很好,不过代码推荐记搜的形式,不仅易于理解,还短. 数位dp的式子一 ...

  8. uva12063数位dp

    辣鸡军训毁我青春!!! 因为在军训,导致很长时间都只能看书yy题目,而不能溜到机房鏼题 于是在猫大的帮助下我发现这道习题是数位dp 然后想起之前讲dp的时候一直在补作业所以没怎么写,然后就试了试 果然 ...

  9. 数位dp总结

    由简单到稍微难点. 从网上搜了10到数位dp的题目,有几道还是很难想到的,前几道基本都是模板题,供入门用. 点开即可看题解. hdu3555 Bomb hdu3652 B-number hdu2089 ...

随机推荐

  1. 前端之JavaScript 03

    window对象 所有浏览器都支持 window 对象.概念上讲.一个html文档对应一个window对象.功能上讲: 控制浏览器窗口的.使用上讲: window对象不需要创建对象,直接使用即可. W ...

  2. (效果二)js实现两个变量值的交换

    ES5: var a = 12,b=13,c; c = a; a = b; b = c; console.log(a,b);//13,12 通过设置第三方变量交换赋值来实现   ES6 var a = ...

  3. php curl请求。header头中添加请求信息

    function get_data($key,$authorization,$url){ $headers = array(    'api-key:'.$key,    'authorization ...

  4. linux操作系统安全防护

    Linux系统攻防对抗实践 一.实践内容 在Metasploit渗透攻击框架软件中寻找一个针对Linux系统服务的渗透攻击模块,在网络安全攻防实验环境中部署有漏洞的环境(如渗透利用第三方网络服务,需要 ...

  5. fn project 对象模型

    Applications At the root of everything are applications. In fn, an application is essentially a grou ...

  6. 为加载......符号 vs2012调试缓慢解决方案

    调试C#网站时vs2012一直 为xxx加载符号 本机上的2010 2017 没有此毛病 没一步都要等待好几秒,百度狗狗(大概花了半天时间)后的方法无果 最后在vs官方论坛 好多老外说删除全部断点就行 ...

  7. JAVA反射调用方法

    1.用户类 package com.lf.entity; import com.lf.annotation.SetProperty; import com.lf.annotation.SetTable ...

  8. Ubantu中sublime汉化

    1 启动并进入sublime主界面: 2 如图所示,点击菜单栏中“preferences”,弹出选项中找到“package control”: 3 进入下一步,选择“install package”: ...

  9. bzoj 5093 [Lydsy1711月赛]图的价值——第二类斯特林数

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5093 不要见到组合数就拆! 枚举每个点的度数,则答案为 \( n*\sum\limits_{ ...

  10. Restore Nexus 5 to Stock and Flash Factory Images

    1.This is the website to download Factory Images for Nexus Devices https://developers.google.com/and ...