前言

最近学了数位DP,感觉挺简单又实用。这道题就比较水,可以用300B的贪心过掉…网上似乎大多是贪心的题解,我就写写DP的做法


题意

  • 给出正整数区间[L,R][L,R][L,R],定义荒谬值为 (去掉后导零的数的长度)*2-[去掉后导零之后末位为5]。求荒谬值最小的数。若有多个则输出最小值。
  • 状态定义为 (i,s,cnt0,flg,fl,fr)(i,s,cnt0,flg,f_l,f_r)(i,s,cnt0,flg,fl​,fr​)
    • int iint\ iint i:表示当前在第 iii 位(最低位为 111 )
    • int jint\ jint j:有效长度为 sss,即从第一个非零位开始记的长度
    • int cnt0int\ cnt0int cnt0:末尾有几个零
    • bool flgbool\ flgbool flg:去掉后导零之后末位是否为 555
    • bool frbool\ f_rbool fr​:是否达到下限
    • bool frbool\ f_rbool fr​:是否达到上限
  • 这里的 fl,frf_l,f_rfl​,fr​ 是数位DP常用的限制数字大小的方法
  • 因为既要保证荒谬值,又要答案最小,就用一个结构体存下荒谬值和对应的最小答案就行了。转移十分简单。因为数的长度最大为 101010,状态数为O(10∗10∗10∗2∗2∗2)=O(8000)O(10*10*10*2*2*2)=O(8000)O(10∗10∗10∗2∗2∗2)=O(8000)
  • 要注意每次都要清零,因为即使 状态一样且没有达到上限或者下限 的时候最小答案也会受[L,R][L,R][L,R]的影响 (没看懂的先看代码,再看下面的UpdUpdUpd)
  • 还有注意存LLL、RRR的数组也要清零

AC代码

#include <bits/stdc++.h>
using namespace std;
const int inf = 1e9+1;
struct node {
int x, y;
node(int _x=0, int _y=0):x(_x), y(_y){}
inline node operator +(const node &t)const {
if(x < t.x) return *this;
if(x > t.x) return t;
return node(x, min(y, t.y));
}
};
node f[11][11][11][2];
bool vis[11][11][11][2];
int dl[11], dr[11]; inline node dfs(int len, int s, int cnt0, bool flg, bool fl, bool fr, int tmp) {
if(!len) return node((flg ? 2*(s-cnt0)-1 : 2*(s-cnt0)), tmp);
if(!fl && !fr && vis[len][s][cnt0][flg]) return f[len][s][cnt0][flg];
node res = node(inf, inf);
int mn = fl ? dl[len] : 0, mx = fr ? dr[len] : 9;
for(int i = mn; i <= mx; ++i)
res = res + dfs(len-1, s+(s||i), i?0:cnt0+1, i ? i==5: flg, fl&&i==mn, fr&&i==mx, tmp*10+i);
if(!fl && !fr) {
vis[len][s][cnt0][flg] = 1;
f[len][s][cnt0][flg] = res;
}
return res;
} inline int solve(int l, int r) {
memset(dl, 0, sizeof dl); //清零2
memset(dr, 0, sizeof dr);
int lenl = 0, lenr = 0;
while(l) dl[++lenl] = l % 10, l /= 10;
while(r) dr[++lenr] = r % 10, r /= 10;
node res = dfs(lenr, 0, 0, 0, 1, 1, 0);
return res.y;
}
int L, R;
int main () {
int T;
scanf("%d", &T);
while(T--) {
memset(vis, 0, sizeof vis); //清零 1 (让我WA到自闭)
scanf("%d%d", &L, &R);
printf("%d\n", solve(L, R));
}
}

Upd:Upd:Upd:之所以会受影响,是因为我算答案的时候,带入了tmptmptmp计算。第一次进去的时候能保证数答案在[L,R][L,R][L,R]内,但如果记忆化后[L,R][L,R][L,R]改变了,就不能保证在区间里面。

BZOJ 4029 [HEOI2015] 定价 ( 数位DP/贪心 )的更多相关文章

  1. BZOJ 4029 HEOI2015 定价 数位贪心

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4029 题意概述:对于一个数字的荒谬程度定义如下:删除其所有的后缀0,然后得到的数字长度为a ...

  2. BZOJ 4029: [HEOI2015]定价 贪心

    4029: [HEOI2015]定价 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4029 Description 在市场上有很多商品的 ...

  3. BZOJ 4029 [HEOI2015]定价

    题解: !!!!!! 分类讨论,情况挺多 #include<iostream> #include<cstdio> #include<cstring> using n ...

  4. BZOJ 3652: 大新闻(数位DP+概率论)

    不得不说数位DP和博弈论根本不熟啊QAQ,首先这道题嘛~~~可以分成两个子问题: 有加密:直接算出0~n中二进制每一位为0或为1分别有多少个,然后分位累加求和就行了= = 无加密:分别算出0~n中二进 ...

  5. BZOJ 1833 数字计数 数位DP

    题目链接 做的第一道数位DP题,听说是最基础的模板题,但还是花了好长时间才写出来..... 想深入了解下数位DP的请点这里 先设dp数组dp[i][j][k]表示数位是i,以j开头的数k出现的次数 有 ...

  6. BZOJ 4521 [CQOI2016]手机号码 - 数位DP

    Description 在$[L, R]$找出有几个数满足两个条件 : 1 : 不同时含有$4$ 和 $8$ 2 : 至少有$3$个相邻的数相同 Solution 非常容易的数位DP, $pos$ 为 ...

  7. BZOJ 3131 [SDOI2013]淘金 - 数位DP

    传送门 Solution 这道数位$DP$看的我很懵逼啊... 首先我们肯定要先预处理出 $12$位乘起来的所有的可能情况, 记录入数组 $b$, 发现个数并不多, 仅$1e4$不到. 然后我们考虑算 ...

  8. BZOJ 1799 同类分布(数位DP)

    给出a,b,求出[a,b]中各位数字之和能整除原数的数的个数.1<=a<=b<=1e18. 注意到各位数字之和最大是153.考虑枚举这个东西.那么需要统计的是[0,a-1]和[0,b ...

  9. bzoj 3329: Xorequ【数位dp+矩阵乘法】

    注意第一问不取模!!! 因为a+b=a|b+a&b,a^b=a|b-a&b,所以a+b=a^b+2(a&b) x^3x==2x可根据异或的性质以转成x^2x==3x,根据上面的 ...

随机推荐

  1. JS 定时器/延时器

    定时器 创建定时器    window.setInterval(方法类型,间隔时间(1000=1秒)) var timer=window.setInterval(func,2000); var i=0 ...

  2. C++中如何记录程序运行时间

    一.clock()计时函数clock()是C/C++中的计时函数,而与其相关的数据类型是clock_t.在MSDN中,查得对clock函数定义如下:clock_t clock(void) ;简单而言, ...

  3. python中列表之间求差集、交集、并集

    求两个列表的交集.并集.差集 def diff(listA, listB): # 求交集的两种方式 retA = [i for i in listA if i in listB] retB = lis ...

  4. go 包的概念

    ------------------------------------------------------------------ package main import ( "fmt&q ...

  5. 【数据结构】P1165 日志分析

    题目描述 MM 海运公司最近要对旗下仓库的货物进出情况进行统计.目前他们所拥有的唯一记录就是一个记录集装箱进出情况的日志.该日志记录了两类操作:第一类操作为集装箱入库操作,以及该次入库的集装箱重量:第 ...

  6. js 监听键盘的enter键

    // js 版本 window.onload=function(){ document.onkeydown=function(ev){ var event=ev ||event if(event.ke ...

  7. 无法访问VMWARE虚拟机中linux的nginx地址

    取得root权限,然后在centos(6.5)中关闭防火墙: service iptables stop 关闭后在windows 10 中浏览器通过虚拟机的ip地址可以直接访问了. 经过测试,打开ip ...

  8. C# 对象互转

    /// <summary> /// 适用于初始化新实体 /// </summary> static public T RotationMapping<T, S>(S ...

  9. 22-MySQL DBA笔记-其他产品的选择

    第22章 其他产品的选择 本章将为读者介绍其他的数据库产品,主要是NoSQL产品的选择.读者在熟悉MySQL之外,也应该了解其他的数据库产品.本章的目的是给读者一个引导,如何选择一些NoSQL产品,而 ...

  10. [前端]多线程在前端的应用——Javascript的线程

    JavaScript 是单线程.异步.非阻塞.解释型脚本语言.JavaScript 的设计就是为了处理浏览器网页的交互(DOM操作的处理.UI动画等),决定了它是一门单线程语言.如果有多个线程,它们同 ...