luogu2657-Windy数题解--数位DP
题目链接
https://www.luogu.org/problemnew/show/P2657
分析
第一道数位DP题,发现有点意思
DP求\([L,R]\)区间内的XXX个数,很套路地想到前缀和,先求\([1,R],[1,L]\)相减就好了
状态转移也明确,发现状态只和上一位数位的数有关,\(f[i][j]\)表示第\(i\)位放\(j\)的话有多少个windy数,注意的这里的windy数是在钦定一个数字最高位是多少情况下所有的windy数的数量和(即[1,i-1]位放数情况都被算了一遍)
\(f[i][j] = f[i-1][ j-2/j+2]\)
然后考虑怎么求答案.
假如我们要求\(1\)到\(R\)中的windy数有多少,设R有x位,第i位数字为num[i]
首先对于位数小于\(x\)的以及第\(x\)位数字小于\(num[x]\)都可以算进去
然后考虑卡到R边界的情况,我们可以枚举前k位卡到了上限即前\(k\)位与R的前\(k\)位相同,那么在第\(k+1\)位进行答案统计
首先我们是不能达到上界的(这样的话可能算多次),在枚举\(k+1\)位的数字为\(d\)时根据定义只有当\(abs(d-a[k])>=2\)时才能累计答案
但是还有一个问题就是你本身枚举与R相等的前k位数可能就违反了windy数的定义,那么我们需要特判一下退出,但是还需要注意由于这个原因我们需要倒序枚举,因为正序枚举的话如果你前面有一对数是非法的,无论后面数位为何值整个数就是非法的
还有一些奇奇怪怪的问题比如前导\(0\).不过这个也挺好想的.
最后发现如果\(R\)也是个windy数的话没判到(我们的卡上界实际上是没有卡到的,我们总是在当前枚举的这一位比R小),所以特判一下就好了
代码
/*
code by RyeCatcher
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <utility>
#include <queue>
#include <vector>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <iostream>
#define DEBUG freopen("dat.in","r",stdin);freopen("wa.out","w",stdout);
#define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
#define ri register int
#define ll long long
#define ull unsigned long long
#define SIZE 1<<22
using std::min;
using std::max;
using std::priority_queue;
using std::queue;
using std::vector;
using std::pair;
using namespace __gnu_pbds;
inline char gc(){
static char buf[SIZE],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,SIZE,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
template <class T>inline void read(T &x){
x=0;int ne=0;char c;
while((c=gc())>'9'||c<'0')ne=c=='-';x=c-48;
while((c=gc())>='0'&&c<='9')x=(x<<3)+(x<<1)+c-48;x=ne?-x:x;return ;
}
const int maxn=12;
const int inf=0x7fffffff;
int a,b;
int toa=0,numa[maxn],tob=0,numb[maxn],f[maxn][maxn];
int main(){
int x,y;
read(a),read(b);
for(ri i=0;i<=9;i++)f[1][i]=1;
x=a;
while(x){
numa[++toa]=x%10;
x=x/10;
}
x=b;
while(x){
numb[++tob]=x%10;
x=x/10;
}
bool flag=1;
for(ri i=2;i<=tob;i++)if(abs(numb[i]-numb[i-1])<2){flag=0;break;}
for(ri i=2;i<=tob;i++){
for(ri j=0;j<=9;j++){
for(ri k=0;k<=9;k++){
if(abs(k-j)>=2)f[i][j]+=f[i-1][k];
}
}
}
ll ans=0;
ans+=flag;
for(ri i=1;i<numb[tob];i++)ans+=f[tob][i];
for(ri i=1;i<tob;i++){
for(ri j=1;j<=9;j++)ans+=f[i][j];
}
for(ri i=tob-1;i>=1;i--){
for(ri j=0;j<numb[i];j++){
if(abs(j-numb[i+1])>=2)ans+=f[i][j];
}
if(abs(numb[i]-numb[i+1])<2)break;
}
for(ri i=1;i<numa[toa];i++)ans-=f[toa][i];
for(ri i=1;i<toa;i++){
for(ri j=1;j<=9;j++)ans-=f[i][j];
}
for(ri i=toa-1;i>=1;i--){
for(ri j=0;j<numa[i];j++){
if(abs(j-numa[i+1])>=2)ans-=f[i][j];
}
if(abs(numa[i]-numa[i+1])<2)break;
}
printf("%lld\n",ans);
return 0;
}
luogu2657-Windy数题解--数位DP的更多相关文章
- 洛谷P2657 [SCOI2009]windy数 题解 数位DP
题目链接:https://www.luogu.com.cn/problem/P2657 题目大意:找区间 \([A,B]\) 范围内 不含前导零 且 相邻两个数字之差至少为2 的正整数的个数. 题目分 ...
- BZOJ_1026_[SCOI2009]windy数_数位DP
BZOJ_1026_[SCOI2009]windy数_数位DP 题意:windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道, 在A和B之 ...
- windy数(简单数位DP)
1026: [SCOI2009]windy数 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 6306 Solved: 2810[Submit][Sta ...
- bzoj1026: [SCOI2009]windy数(数位dp)
1026: [SCOI2009]windy数 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 8203 Solved: 3687[Submit][Sta ...
- [bzoj 1026]windy数(数位DP)
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1026 分析: 简单的数位DP啦 f[i][j]表示数字有i位,最高位的数值为j的windy数总 ...
- bzoj 1026 [SCOI2009]windy数(数位DP)
1026: [SCOI2009]windy数 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 4550 Solved: 2039[Submit][Sta ...
- windy数(数位DP)
windy数Crawling in process... Crawling failed Time Limit:1000MS Memory Limit:165888KB 64bit I ...
- [bzoj1026][SCOI2009]windy数_数位dp
windy数 bzoj-1026 题目大意:求一段区间中的windy数个数. 注释:如果一个数任意相邻两位的差的绝对值都不小于2,这个数就是windy数,没有前导0.$区间边界<=2\cdot ...
- 2018.06.30 BZOJ1026: [SCOI2009]windy数(数位dp)
1026: [SCOI2009]windy数 Time Limit: 1 Sec Memory Limit: 162 MB Description windy定义了一种windy数.不含前导零且相邻两 ...
- 1026. [SCOI2009]windy数【数位DP】
Description windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道, 在A和B之间,包括A和B,总共有多少个windy数? I ...
随机推荐
- python __iter__ 迭代器
1. 迭代器是什么? 迭代器是一个对象,是python非常强大的特性 根本上说, 迭代器就是有一个 next() 方法的对象, 而不是通过索引来计数. 当你或是一个循环机制(例如 for 语句)需要下 ...
- SQL-W3School-函数:SQL LEN() 函数
ylbtech-SQL-W3School-函数:SQL LEN() 函数 1.返回顶部 1. LEN() 函数 LEN 函数返回文本字段中值的长度. SQL LEN() 语法 SELECT LEN(c ...
- 优雅编写Python3 的62个小贴士
iterable技巧 ▍1.创建一个数字序列(从0到10,间隔为2) >>> range(0,10,2)[0, 2, 4, 6, 8] ▍2.对一串数字求和(从0到10,间隔为2 ...
- 阶段5 3.微服务项目【学成在线】_day17 用户认证 Zuul_11-前端显示当前用户-前端请求jwt
前端代码 sessionStorage也是key/value的格式 页头显示当前用户 查询jwt nginx里面的配置 测试 开启认证服务 进行登陆 跳转到首页就应该立即请求查询. 跳转到首页 coo ...
- java精确计算工具类
java精确计算工具类 import java.math.BigDecimal; import java.math.RoundingMode; import java.math.BigDecimal; ...
- python面试必备-基础篇
一.python中and, or, and-or语法 1.and 有假先出假 在Python 中,and 和 or 执行布尔逻辑演算,如你所期待的一样,但是它们并不返回布尔值:而是,返回它们实际进 ...
- python高级知识
网络udp socket的作用 进程指的是:运行的程序以及运行时用到的资源这个整体称之为进程 socket(简称 套接字) 是最通用的进程间通信的一种方式 创建socket import socket ...
- SpringCloud学习成长之十二 断路器监控
在我的第四篇文章断路器讲述了如何使用断路器,并简单的介绍了下Hystrix Dashboard组件,这篇文章更加详细的介绍Hystrix Dashboard. 一.Hystrix Dashboard简 ...
- LD_LIBRARY_PATH无效
在os x 上设置LD_LIBRARY_PATH无效,env命令看不到这个变量,下面的文章说明了这个问题 说明:网上基本针对这个值的设置分为两面,Windows派和Linux派,Windows的不说, ...
- 【python比较两个列表list】 python2 cmp() python3 operator模块
https://www.yiibai.com/python/list_cmp.html 如果元素的类型相同,则执行比较并返回结果.如果元素是不同的类型,则检查它们是否是数字. 如果数字,必要时进行数字 ...