开坑数位dp
【背景】
在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的更多相关文章
- 数位dp踩坑
前言 数位DP是什么?以前总觉得这个概念很高大上,最近闲的没事,学了一下发现确实挺神奇的. 从一道简单题说起 hdu 2089 "不要62" 一个数字,如果包含'4'或者'62', ...
- 【距离GDOI:141天】 滚入数位DP的坑
作为博客园的第一篇...我都不知道要写什么了 ... 其实今天很没状态,就当吐槽吧... 嗯,被黄神带去写treap+可持久化线段树,然后在可持久化的删除上面跪了两天,真的是一跪不起.我已经连续多久没 ...
- # 数位DP入坑
Hdu 2089 不要62 #include<iostream> #include<cstdio> #include<cmath> #include<cstr ...
- 浅谈数位DP
在了解数位dp之前,先来看一个问题: 例1.求a~b中不包含49的数的个数. 0 < a.b < 2*10^9 注意到n的数据范围非常大,暴力求解是不可能的,考虑dp,如果直接记录下数字, ...
- 数位DP入门:(bzoj1833+3209)
//我是来看文章创建时间的= = 膜拜了一下蔡大神.... 人生第一道自己写的数位DP...好吧以前是看题解然后也不知道为什么就过了的>_< 虽然说现在还是只会裸题= = 数位DP介绍: ...
- 数位dp初探
我这种蒟蒻就一直不会写数位dp.. 于是开了个坑.. 1833: [ZJOI2010]count 数字计数 这道被KPM大爷说是入门题..嗯似乎找找规律然后减掉0的情况后乱搞就可以了..(但是还是写了 ...
- 数位dp小练
最近刷题的同时还得填填坑,说来你们也不信,我还不会数位dp. 照例推几篇博客: 数位DP讲解 数位dp 的简单入门 这两篇博客讲的都很好,不过代码推荐记搜的形式,不仅易于理解,还短. 数位dp的式子一 ...
- uva12063数位dp
辣鸡军训毁我青春!!! 因为在军训,导致很长时间都只能看书yy题目,而不能溜到机房鏼题 于是在猫大的帮助下我发现这道习题是数位dp 然后想起之前讲dp的时候一直在补作业所以没怎么写,然后就试了试 果然 ...
- 数位dp总结
由简单到稍微难点. 从网上搜了10到数位dp的题目,有几道还是很难想到的,前几道基本都是模板题,供入门用. 点开即可看题解. hdu3555 Bomb hdu3652 B-number hdu2089 ...
随机推荐
- 解放内存之搭建自己的 R Server
学校的课五门有四门需要跑R程序,有一些长长长的代码实在是占用了太多的内存,果断决定搭个R的服务器放着自己跑. 愉快的是,R studio server 的搭建真心简单快捷~这个从前被我忽略的东东终于排 ...
- linux中文件或者文件夹的基本操作(复制,移动,删除,查找,压缩)
linux 文件(文件夹)的创建,复制,移动,重命名,删除基本命令 复制文件或整个目录 cp 源文件名 目标文件夹/[目标文件名]cp -rv 源文件夹 目标文件夹/[目标文件夹名] --r 递归目录 ...
- 剑指offer-第四章解决面试题思路(判断一个数组是否为二叉搜索树的后序遍历序列)
二叉搜索树:二叉搜索树根节点的左边都比根节点小,右边都比根节点大. 例题:输入一个数组,判断是否为二叉搜索树的后序遍历序列,如果是,返回true,如果不是,返回flase,假设没有重复的元素. 思路: ...
- SqlServer2008 新建服务器对象->链接服务器脚本
exec sp_addlinkedserver 'ddxx', '', 'SQLOLEDB','1.192.168.220'exec sp_addlinkedsrvlogin 'ddxx','fa ...
- iOS 10 隐私权限设置
iOS 10 开始对隐私权限更加严格,如果你不设置就会直接崩溃,现在很多遇到崩溃问题了,一般解决办法都是在info.plist文件添加对应的Key-Value就可以了. 以上Value值,圈出的红线部 ...
- kafka ksql && docker 安装试用
备注: 使用docker 模式进行安装 1. 准备docker 环境(需要docker-compose) docker 的安装不需要进行多描述了,直接yum 或者源码编译也可以 ...
- Oracle创建实例
1.打开database configuration assistant 2.下一步 3.下一步 4.完成 5.添加完密码后,点击关闭.
- Visual Studio Code教程:基础使用和自定义设置
一.界面介绍 1.1 界面介绍 1.2 文件夹和文件的打开 文件——>打开文件夹/打开文件 1.3 新建文件/文件夹 新建文件: a. 文件——>新建文件: b. 按Ctrl+n; c. ...
- 软件开发中IT用语-日文和英文对照版
開発工程 † 要件定義…Requirement Definition (Analyze) 外部設計…External Design 内部設計…Internal Design 開発…Coding テスト ...
- ecshop其他页面判断是智能手机访问也跳转到ECTouch对应手机版页面(转)
ecshop 其他页面(商品详情页.商品分类页.团购页.优惠活动页.积分商城) 判断如果是智能手机访问跳转到ECTouch1.0手机版对应页面 方法 首先在ecshop 根目录下 includes/l ...