数位dp小练
最近刷题的同时还得填填坑,说来你们也不信,我还不会数位dp。
照例推几篇博客:
数位DP讲解
数位dp 的简单入门
这两篇博客讲的都很好,不过代码推荐记搜的形式,不仅易于理解,还短。
数位dp的式子一般是这样的:dp[i][][]表示到第\(i\)位,而后面几维就因题而异了。
不过通用的思想就是利用前缀相减求出区间信息。
算了上题吧。
[SCOI2009]windy数
这都说是数位dp入门题。
根据这题,受到影响的数只有相邻两个,因此dp[i][j]表示到第\(i\)位(从高往低)上一位的数\(j\)的答案。
接下来的关键在于怎么判断到达上界的情况。那么我们在搜索的时候加一个bool变量_Max表示是否到达上界,如果是,那么这一位的最大值就是该位上的数,否则就是9。
然后关于前导零,我又开了一个bool变量zero判断他之前有没有过非0的数。
接下来就是记搜的内容了。先写一个爆搜,然后把答案存在dp里,基本就是记搜了。
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 12;
inline ll read()
{
ll ans = 0;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) last = ch, ch = getchar();
while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < 0) x = -x, putchar('-');
if(x >= 10) write(x / 10);
putchar(x % 10 + '0');
}
int dp[maxn][maxn], num[maxn], cnt = 0;
In int dfs(int len, int las, bool _Max, bool zero)
{
if(!len) return 1; //表示出现了一个符合条件的数,就返回1
if(!_Max && !zero && dp[len][las] != -1) return dp[len][las];
//只有普通情况才可以返回记搜的答案.
int pos, ret = 0, Max = _Max ? num[len] : 9;
for(int i = 0; i <= Max; ++i)
{
if(abs(i - las) < 2) continue;
pos = (zero && !i) ? -INF : i; //如果前面都是0且这一位还填0,就标记为INF
ret += dfs(len - 1, pos, _Max && i == Max, pos == -INF);
}
if(!_Max && !zero) dp[len][las] = ret;
return ret;
}
In int solve(int n)
{
Mem(dp, -1); cnt = 0;
while(n) num[++cnt] = n % 10, n /= 10; //处理每一位
return dfs(cnt, -INF, 1, 1);
}
int main()
{
int a = read(), b = read();
write(solve(b) - solve(a - 1)), enter;
return 0;
}
**[luogu P3413 SAC#1 - 萌数](https://www.luogu.org/problemnew/show/P3413)**
这题反正我是不会,看了题解也没懂。最后在dukelv的帮助下搞明白了。
首先题解中有很多篇用了正难则反的思想,但其实没必要。
考虑最小的回文串,无非两种:aa, aba。
所以我们只用找出这两种回文串即可。因为大的回文串比如acbbca,在搜bb的时候,下几个状态就包括这个回文串了。
那么就要讨论奇偶,所以爆搜的时候开两个变量pre,per分别记录上一位和上上一位,然后判断和当前位是否构成回文串。
别忘了还可能会出现构不成萌数的情况,所以dp方程除了dp[i][j]表示到了第$i$位,这一位填$i$,还应再加一位[0/1]表示当前是否存在萌数,这样能剪枝不少。
```c++
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 1e3 + 5;
const ll mod = 1e9 + 7;
inline ll read()
{
ll ans = 0;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) last = ch, ch = getchar();
while(isdigit(ch)) ans = (ans = 10) write(x / 10);
putchar(x % 10 + '0');
}
char a[maxn], b[maxn];
int num[maxn], len = 0;
ll dp[maxn][10][2];
In ll dfs(int pos, int pre, int per, bool _t, bool _k, bool _Max)
{
if(!pos) return _t; //_t表示当前是否存在萌数
if(!_Max && dp[pos][pre][_t] != -1) return dp[pos][pre][_t];
int Max = _Max ? num[pos] : 9;
ll ret = 0;
for(int i = 0; i <= Max; ++i)
ret += dfs(pos - 1, i, _k ? pre : -1, _t || (i == pre && _k) || (i == per && _k), _k || i, _Max && i == Max), ret %= mod;
if(!_Max && _k && per != -1) dp[pos][pre][_t] = ret % mod;
return ret;
}
In ll solve(char* s)
{
len = strlen(s + 1);
for(int i = 1; i <= len; ++i) num[i] = s[i] - '0';
reverse(num + 1, num + len + 1);
Mem(dp, -1);
return dfs(len, -1, -1, 0, 0, 1);
}
int main()
{
scanf("%s%s", a + 1, b + 1);
int tp = strlen(a + 1);
reverse(a + 1, a + tp + 1);
int pos = 1; //别忘了是高精减1……
--a[pos];
while(pos < tp && a[pos] < '0') a[pos++] = '9', --a[pos];
while(tp > 1 && a[tp] <= '0') a[tp--] = '\0';
reverse(a + 1, a + tp + 1);
write((solve(b) - solve(a) + mod) % mod), enter;
return 0;
}
数位dp小练的更多相关文章
- 【树形dp小练】HDU1520 HDU2196 HDU1561 HDU3534
[树形dp]就是在树上做的一些dp之类的递推,由于一般须要递归处理.因此平庸情况的处理可能须要理清思路.昨晚開始切了4题,作为入门训练.题目都很easy.可是似乎做起来都还口以- hdu1520 An ...
- 牛客寒假算法基础集训营3处女座和小姐姐(三) (数位dp)
链接:https://ac.nowcoder.com/acm/contest/329/G来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言52428 ...
- 处女座和小姐姐(三)(数位dp)
链接:https://ac.nowcoder.com/acm/contest/329/G 来源:牛客网 题目描述 经过了选号和漫长的等待,处女座终于拿到了给小姐姐定制的手环,小姐姐看到以后直呼666! ...
- [bzoj3209][花神的数论题] (数位dp+费马小定理)
Description 背景众所周知,花神多年来凭借无边的神力狂虐各大 OJ.OI.CF.TC …… 当然也包括 CH 啦.描述话说花神这天又来讲课了.课后照例有超级难的神题啦…… 我等蒟蒻又遭殃了. ...
- P2188 小Z的 k 紧凑数 题解(数位DP)
题目链接 小Z的 k 紧凑数 解题思路 数位DP,把每一个数位的每一个数对应的可能性表示出来,然后求\(num(1,r)-num(1,l-1)\),其中\(num(i,j)\)表示\([i,j]\)区 ...
- 数位DP之小小结
资料链接:http://wenku.baidu.com/view/9de41d51168884868662d623.html http://wenku.baidu.com/view/d2414ffe0 ...
- 牛客训练三:处女座和小姐姐(三)(数位dp)
题目链接:传送门 思路:数位dp的记忆化搜索模板 从高位向低位枚举,逐位确定每一位的6的个数,dp[i][s]表示处理到第i条边,状态为s时的数字的个数. 注意,要使用long long类型. #in ...
- SCUT - 289 - 小O的数字 - 数位dp
https://scut.online/p/289 一个水到飞起的模板数位dp. #include<bits/stdc++.h> using namespace std; typedef ...
- [CSP-S模拟测试]:小L的数(数位DP+模拟)
题目传送门(内部题132) 输入格式 第一行一个整数$t$. 接下来$t$行每行一个整数$n$. 输出格式 $t$行,每行一个整数表示答案. 样例 样例输入: 41818231232691052109 ...
随机推荐
- FFmpeg封装格式处理
本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10506636.html FFmpeg封装格式处理相关内容分为如下几篇文章: [1]. F ...
- Linux 下 rt3070 无线网卡找不到 firmware 问题
解决办法: 下载好固件 rt2800.bin 文件,复制到 /lib/firmware 中 如果完成以上步骤后,运行 ifconfig wlan0 up 仍然提示 phy0 -> rt2x00l ...
- [Python] Python基础字符串
Python的语法采用缩进的方式,一般使用四个空格,并且是大小写敏感的 字符编码 计算机只能处理数字,如果要处理文本,必须先把文本转换成数字才能处理 采用8个比特(bit)作为一个字节(byte) 一 ...
- GCC链接的几个注意点
库文件依赖顺序 GCC在链接时对依赖库的顺序是敏感的,被依赖的库必须放在后面,比如liba.a依赖libb.a,必须写成liba.a libb.a,否则链接将出错.在库比较多依赖关系比较复杂或者相互依 ...
- Nodejs 和 Electron ubuntu下快速安装
查找时间管理软件的时候发现了superProductivity这个程序,使用electron进行开发,于是看了一下介绍,手痒了,尝试进行环境搭建,下一步慢慢补齐前端知识吧 nodejs安装 nodej ...
- spring boot 随手记
1.当加入security 起步依赖后,如果不做任何手动配置的话,默认会跳转到一个登录页面,不管你喜不喜欢,所有的请求都必须登录,用户名和密码是保存在内存中的, 默认用户名是user 密码在控制台里 ...
- JS 数组位置方法 indexOf()和lastIndexOf()的理解
var numbers = [1,3,5,7,9,4,3,2,1]; console.log(numbers.indexOf(5)); //从数组的0位开始查找 5 位于数组里面的位置 输出2 首先 ...
- CSS3属性-webkit-font-smoothing字体抗锯齿渲染
对字体进行抗锯齿渲染可以使字体看起来会更清晰舒服.在图标字体成为一种趋势的今天,抗锯齿渲染使用也越来越多. font-smoothing是非标准的CSS定义.它被列入标准规范的草案中,后由于某些原因从 ...
- html的标签分类————body内标签系列
超链接标签 <a href="" target="_blank">text</a>,此类标签通常是超链接.其中href后面跟进的是超链接 ...
- docker-使用Dockerfile制作镜像
最近项目中有使用docker,组内做了关于docker的培训,然后自己跟着研究了一下,大概了解如何使用.我是基于tomcat镜像制作(不需要安装jdk,配置环境变量),基于centos镜像制作需要安装 ...