感觉数位dp好恶心……

原题:

人们选择手机号码时都希望号码好记、吉利。比如号码中含有几位相邻的相同数字、不含谐音不
吉利的数字等。手机运营商在发行新号码时也会考虑这些因素,从号段中选取含有某些特征的号
码单独出售。为了便于前期规划,运营商希望开发一个工具来自动统计号段中满足特征的号码数
量。
工具需要检测的号码特征有两个:号码中要出现至少3个相邻的相同数字,号码中不能同
时出现8和4。号码必须同时包含两个特征才满足条件。满足条件的号码例如:13000988721、
23333333333、14444101000。而不满足条件的号码例如:1015400080、10010012022。
手机号码一定是11位数,前不含前导的0。工具接收两个数L和R,自动统计出[L,R]区间
内所有满足条件的号码数量。L和R也是11位的手机号码。
10^10 < =  L < =  R < 10^11
 
数位dp好恶心>π<
f[i][flag1][last1][last2][flag2][flag3]
第i位,有没有到顶(0表示到了,1表示没到),前一个是啥,再前一个是啥,关于4和8的状态(两个压成了一维),有没有三连(稽
然后这里要从高往低,设flag为4和8的状态,mark为三连(稽)的状态
初始状态就是f[2][0][a[1]][a[2]][flag][0]=1,因为从高往低dp,所以a也是从高位彺低位
注意不用担心这里的1会直接被算到答案里的情况,因为flag不一定不为3(为3表示有4又有8),同时mark=0,所以这个1对答案没贡献,但是可能会对其它合法的状态有贡献
然后对于每一位首先需要判断一下上限是否会对其它状态贡献,就在循环外面开一个flag'和一个mark',表示上限的状态
每到1为flag'|=a[i]关于4或8的状态,mark'|=是否和前面两个形成三连(稽)
如果flag不等于3,即状态合法,那么f[i][0][a[i-1]][a[i-2]][flag][mark]=1
为啥mark等于0的时候依旧会贡献?因为flag这次完了就真的完了,mark暂时没有三连(稽)以后还可以翻
然后枚举上一位k,再上一位j,再上一位q,以及关于4和8的状态p
转移式如下:

f[i][1][k][q][flag][1]+=(q<a[i])*f[i-1][0][j][k][p][1]+f[i-1][1][j][k][p][1];
f[i][1][k][q][flag][mark]+=(q<a[i])*f[i-1][0][j][k][p][0]+f[i-1][1][j][k][p][0];

恩再多我也解释不了了,只能意会

全程抄代码,感觉只是勉强理解了这题,并不能自己写出来

注意l=1e10的情况,减一下就不是11位了

代码:

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define ll long long
ll n,m;
int a[];
ll f[][][][][][];
int QAQ(int x,int y){ return ((x==)<<)|(x==)|((y==)<<)|(y==);}
ll play(ll x){
memset(f,,sizeof(f));
for(int i=;i>=;--i) a[i]=x%,x/=;
int flg=QAQ(a[],a[]),mk=;
f[][][a[]][a[]][flg][]=;
for(int i=;i<=a[];++i)for(int j=;j<=;++j){
if(i==a[] && j>=a[]) continue;
f[][][i][j][QAQ(i,j)][]=;
}
for(int i=;i<=;++i){
flg|=QAQ(a[i],a[i]),mk|=(a[i]==a[i-] && a[i]==a[i-]);
if(flg!=) f[i][][a[i-]][a[i]][flg][mk]=;
for(int j=;j<=;++j)for(int k=;k<=;++k)for(int p=;p<=;++p)for(int q=;q<=;++q){
int flg1=p|QAQ(q,q),flg2=(q==k && k==j);
if(flg1==) continue;
f[i][][k][q][flg1][]+=(q<a[i])*f[i-][][j][k][p][]+f[i-][][j][k][p][];
f[i][][k][q][flg1][flg2]+=(q<a[i])*f[i-][][j][k][p][]+f[i-][][j][k][p][];
}
}
ll bwl=;
for(int i=;i<=;++i)for(int j=;j<=;++j)for(int p=;p<=;++p)for(int q=;q<=;++q)
bwl+=f[][q][i][j][p][];
return bwl;
}
int main(){//freopen("ddd.in","r",stdin);
cin>>n>>m;
if(n==10000000000LL){ cout<<play(m)<<endl; return ;}
cout<<play(m)-play(n-)<<endl;
return ;
}

【BZOJ4521】【CQOI2016】手机号码的更多相关文章

  1. [BZOJ4521][CQOI2016]手机号码(数位DP)

    4521: [Cqoi2016]手机号码 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 875  Solved: 507[Submit][Status ...

  2. [Bzoj4521][Cqoi2016]手机号码(数位dp)

    4521: [Cqoi2016]手机号码 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 870  Solved: 505[Submit][Status ...

  3. BZOJ4521: [Cqoi2016]手机号码

    Description 人们选择手机号码时都希望号码好记.吉利.比如号码中含有几位相邻的相同数字.不含谐音不 吉利的数字等.手机运营商在发行新号码时也会考虑这些因素,从号段中选取含有某些特征的号 码单 ...

  4. BZOJ4521 Cqoi2016 手机号码 【数位DP】

    Description 人们选择手机号码时都希望号码好记.吉利.比如号码中含有几位相邻的相同数字.不含谐音不吉利的数字等.手机运营商在发行新号码时也会考虑这些因素,从号段中选取含有某些特征的号码单独出 ...

  5. [BZOJ4521][Cqoi2016]手机号码 (数位dp)

    题目描述 人们选择手机号码时都希望号码好记.吉利.比如号码中含有几位相邻的相同数字.不含谐音不吉利的数字等.手机运营商在发行新号码时也会考虑这些因素,从号段中选取含有某些特征的号码单独出售.为了便于前 ...

  6. [bzoj4521][Cqoi2016][手机号码] (数位dp+记忆化搜索)

    Description 人们选择手机号码时都希望号码好记.吉利.比如号码中含有几位相邻的相同数字.不含谐音不 吉利的数字等.手机运营商在发行新号码时也会考虑这些因素,从号段中选取含有某些特征的号 码单 ...

  7. 【BZOJ-4521】手机号码 数位DP

    4521: [Cqoi2016]手机号码 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 303  Solved: 194[Submit][Status ...

  8. 4521: [Cqoi2016]手机号码

    4521: [Cqoi2016]手机号码 Time Limit: 10 Sec Memory Limit: 512 MB Submit: 1030 Solved: 609 [Submit][Statu ...

  9. [CQOI2016]手机号码 数位DP

    [CQOI2016]手机号码 用来数位DP入门,数位DP把当前是否需要限制取数范围(是否正在贴着临界值跑,即下面的limited)和一切需要满足的条件全部塞进记忆化搜索参数里面就好了,具体情况转移便好 ...

  10. P4124 [CQOI2016]手机号码

    P4124 [CQOI2016]手机号码 题解 数位DP   DFS  虽然套路,但还是恶心到找不到锅在哪里 注意这个 然后你就发现其实这样就不用记录前导0了 锅在这个鬼地方QAQ 代码 #inclu ...

随机推荐

  1. Ubuntu下怎么编译并运行C、C++和Pascal语言?

    很多同学在安装了Ubuntu的环境后,发现在Windows下的许多东西都打不开了,但是用网站上的在线IDE又不是很方便. 所以,ljn教你如何在Ubuntu下编译并运行C.C++和Pascal. 一. ...

  2. Java冒泡排序与选择排序

    Java排序: 一.冒泡排序算法的运作如下: 比较相邻的元素.如果第一个比第二个大,就交换他们两个. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大的数. ...

  3. Python Django 之 ADMIN

    一.创建project 二.创建app 三.启动Django python manage.py runserver 四.创建admin数据库表

  4. mysql 数据迁移

    最近线上系统新挂了一次磁盘,需要将系统磁盘下的 mysql 数据目录迁移到 数据盘上. 经过一番考察,mysql在安装时,使用了预编译的二进制tar.gz包.共有两处配置了 datadir属性 /et ...

  5. Mysql数据库操作语句总结

    简单复习下: 增insert into -- 删 delete from  -- 改 update table名字 set -- 查 select * from  -- 一.SQL定义 SQL(Str ...

  6. [Leetcode 44]通配符匹配Wildcard Matching

    [题目] 匹配通配符*,?,DP动态规划,重点是*的两种情况 想象成两个S.P长度的字符串,P匹配S. S中不会出现通配符. [条件] (1)P=null,S=null,TRUE (2)P=null, ...

  7. 深入理解java虚拟机---java虚拟机内存管理(七)

    本地方法栈.java堆.方法区 本地方法栈在HotSpot版本内与java虚拟机栈是合二为一的.不单独区分本地方法栈.但是java虚拟机中是有这样一块区域的. 作用: 1.本地方法栈为虚拟机栈执行ja ...

  8. DevExpress v18.1新版亮点——CodeRush for VS篇(二)

    用户界面套包DevExpress v18.1日前正式发布,本站将以连载的形式为大家介绍各版本新增内容.本文将介绍了CodeRush for Visual Studio v18.1 的新功能,快来下载试 ...

  9. 谷歌开源的TensorFlow Object Detection API视频物体识别系统实现(二)[超详细教程] ubuntu16.04版本

    本节对应谷歌开源Tensorflow Object Detection API物体识别系统 Quick Start步骤(一): Quick Start: Jupyter notebook for of ...

  10. 《十天学会单片机和C语言编程》

    <十天学会单片机和C语言编程> 大家注意了这个文件只有最新版迅雷可以下载,下面的lesson几就是第几课.点击右键使用迅雷下载. ed2k://|file|[十天学会单片机和C语言编程]. ...