打了几个数位$dp$,发现自己除了会打模板之外没有任何长进,遇到非模板题依然什么都不会

那么接下来这篇文章将介绍如何打模板(滑稽)

假设我们要处理$l----r$

采用记忆化搜索的方式,枚举$<=r$每一种情况,枚举每一位,然后再枚举$<=l-1$每一种情况,然后两个值相减即可

我们可以比较轻松打出一个模板

ll dfs(ll x,ll pre,ll lead,ll limit){if(x>pos) return 1;if(!limit&&f[x][pre]) return f[x][pre];ll ans=0;ll mx=limit?maxn[pos-x+1]:9;for(ll i=0;i<=mx;i++){if(????????) continue;if(lead&&i==0) ans+=dfs(x+1,-2,1,limit&&(i==mx));else ans+=dfs(x+1,i,0,limit&&(i==mx));}if(!limit&&!lead) f[x][pre]=ans;return ans;
}

解释一下$limit$是什么

假设有一个数

$1\   2\  3\  4\  5\  6$

$1\   2\  3\  ?\  ?\  ?$

我们枚举到第四位时最多枚举到$4$,

$1\   2\  3\  4\  5\  6$

$1\   2\  2\  ?\  ?\  ?$

这时我们枚举到第四位最多枚举到$9$

$limit$就是判断这个的

那么为什么要在$!limit$下才记忆化呢?

如果在所有情况下我们都记录f,那么假如之前枚举到$9$时你记录了一个答案,然后当前位有$limit$限制根本枚举不到$9$,你仍然用了这个f会出现错误

当然你这样记忆化也可以这样避免冲突

ll dfs(ll x,ll limit,ll tmp,ll d){if(f[x][limit][tmp][d]) return f[x][limit][tmp][d];………………    f[x][limit][tmp][d]=ans;return ans;
}

解释一下$lead$

处理前导0用的,

有的时候

$0\   0\  0\  4\  5\  6$

也被认为是合法的,这时处理可能会出现问题,$lead$特判特殊处理

那么我们看几道模板题

例题

windy数

Windy 定义了一种 Windy 数:不含前导零且相邻两个数字之差至少为2的正整数被称为 Windy 数。

Windy 想知道,在l和r 之间,包括l 和 r ,总共有多少个 Windy 数?

非常简单对不对

套模板

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define A 50
ll f[A][A],maxn[A];
ll pos=0,a,b;
ll dfs(ll x,ll pre,ll lead,ll limit){if(x>pos) return 1;if(!limit&&f[x][pre]) return f[x][pre];ll ans=0;ll mx=limit?maxn[pos-x+1]:9;
//    printf("mx=%lld\n",mx);for(ll i=0;i<=mx;i++){if(abs(pre-i)<2) continue;if(lead&&i==0) ans+=dfs(x+1,-2,1,limit&&(i==mx));else ans+=dfs(x+1,i,0,limit&&(i==mx));
//        printf("ans=%lld\n",ans);
    }if(!limit&&!lead) f[x][pre]=ans;return ans;
}
ll solve(ll x){pos=0;memset(f,0,sizeof(f));while(x){maxn[++pos]=x%10;x/=10;}ll ans=dfs(1,-2,1,1);return ans;
}
int main(){scanf("%lld%lld",&a,&b);swap(a,b);printf("%lld\n",solve(a)-solve(b-1));
}

不要62

$l---r$间数位上不含$4$且没有$62$相连的数个数

套模板

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define A 50
ll f[A][A],maxn[A];
ll pos=0,a,b;
ll dfs(ll x,ll pre,ll limit){if(!x) return 1;if(!limit&&f[x][pre]) return f[x][pre];
//    printf("x=%lld pre=%lld  limit=%lld\n",x,pre,limit);ll ans=0;ll mx=limit?maxn[x]:9;for(ll i=0;i<=mx;i++){if(pre==6&&i==2) continue;if(i==4) continue;ans+=dfs(x-1,i,limit&&(i==mx));}
//    printf("ans=%lld\n",ans);if(!limit) f[x][pre]=ans;return ans;
}
ll solve(ll x){pos=0;memset(f,0,sizeof(f));while(x){maxn[++pos]=x%10;x/=10;}ll ans=dfs(pos,0,1);return ans;
}
int main(){a=233,b=233;while(a!=0&&b!=0){scanf("%lld%lld",&a,&b);if(a<b)swap(a,b);if(a==0||b==0){return 0;}printf("%lld\n",solve(a)-solve(b-1));}
}

手机号码

至少$3$个相邻的相同的数,$8$ $4$不能同时出现

套模板,注意下特判,不然会70到自闭

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define A 30
ll f[A][A][A][2][2][2],pos[A];
ll tot=0,a,b;
ll dfs(ll x,ll prer,ll pre,ll limit,ll _4,ll _8,ll ok){if(_4&&_8) return 0;if(x>tot&&!ok) return 0;if(x>tot&&ok) return 1;if(!limit&&f[x][prer][pre][_4][_8][ok]) return f[x][prer][pre][_4][_8][ok];ll maxn=limit?pos[tot-x+1]:9;ll ans=0;for(ll i=0;i<=maxn;i++){if(x==1&&i==0) continue;if(_4&&i==8) continue;if(_8&&i==4) continue;if(pre==prer&&i==pre&&i==prer)ans+=dfs(x+1,pre,i,(limit&&i==maxn),(_4||i==4),(_8||i==8),1);else ans+=dfs(x+1,pre,i,limit&&(i==maxn),(_4||i==4),(_8||i==8),ok);
//        printf("ans=%lld i=%lld maxn=%lld\n",ans,i,maxn);
    }if(!limit)f[x][prer][pre][_4][_8][ok]=ans;return ans;
}
ll solve(ll x){tot=0;if(x<1e10) return 0;memset(f,0,sizeof(f));while(x){pos[++tot]=x%10;x/=10;}ll ans=dfs(1,0,0,1,0,0,0);return ans;
}
int main(){scanf("%lld%lld",&a,&b);if(a<b) swap(a,b);printf("%lld\n",solve(a)-solve(b-1));
}

花神的数论题

设 sum(i) 表示 i 的二进制表示中 1 的个数。给出一个正整数 N ,花神要问你派(Sum(i)),也就是 sum(1)—sum(N) 的乘积。

套模板,等等,我要套什么,

这个题不算很板,值得思考思考。

数位dp计算出所有二进制下sum个数,然后快速幂处理一下,

代码

#include<bits/stdc++.h>
using namespace std;
#define A 53
#define mod 10000007
#define ll long long
ll n,tot=0,sum=0;
ll f[A][2][A][A],ans[A],pos[A];
ll dfs(ll cur,ll up,ll tmp,ll d){if(!cur)return tmp==d;if(~f[cur][up][tmp][d])return f[cur][up][tmp][d];ll lim=up?pos[cur]:1;ll ret=0;for(ll i=0;i<=lim;i++)ret+=dfs(cur-1,up&&i==lim,tmp+(i==1),d);return f[cur][up][tmp][d]=ret;
}
ll meng(ll a,ll b){ll ret=1;while(b)ret=ret*(b&1?a:1)%mod,a=a*a%mod,b>>=1;return ret;
}
ll solve(ll x){sum=1;while(x){pos[++tot]=x&1;x>>=1;}for(ll i=1;i<=tot;i++){memset(f,-1,sizeof(f));ans[i]=dfs(tot,1,0,i);}for(ll i=1;i<=tot;i++){sum=(sum*max(meng(i,ans[i]),1ll))%mod;}return sum;
}
int main(){scanf("%lld",&n);printf("%lld\n",solve(n));
}

剩下一些题都不算很板

数数

淘金

方伯伯商场之旅

题解慢慢补充八

那么你现在会模板了吗?

转载于:https://www.cnblogs.com/znsbc-13/p/11328399.html

数位dp从会打模板到不会打模板相关推荐

  1. 数位DP入门+数位DP模板

    数位dp是一种计数用的dp,一般就是要统计一个区间[le,ri]内满足一些条件数的个数.所谓数位dp,字面意思就是在数位上进行dp咯.数位还算是比较好听的名字,数位的含义:一个数有个位.十位.百位.千 ...

  2. 数位dp模板 [dp][数位dp]

    现在才想到要学数位dp,我是不是很弱 答案是肯定的 以一道自己瞎掰的题为模板 1 //题: 2 //输入数字n 3 //从0枚举到n,计算这n+1个数中含有两位数a的数的个数 4 //如12930含有 ...

  3. 数位dp总结 之 从入门到模板(stO)

    #转载自https://blog.csdn.net/wust_zzwh/article/details/52100392 基础篇 数位dp是一种计数用的dp,一般就是要统计一个区间[le,ri]内满足 ...

  4. 数位dp总结 之 从入门到模板

    转自巨佬:https://blog.csdn.net/wust_zzwh/article/details/52100392 基础篇 数位dp是一种计数用的dp,一般就是要统计一个区间[le,ri]内满 ...

  5. 数位dp【模板 + 老年康复】

    学习博客: 戳这里 戳这里 "在信息学竞赛中,有这样一类问题:求给定区间中,满足给定条件的某个D 进制数或 此类数的数量.所求的限定条件往往与数位有关,例如数位之和.指定数码个数.数的大小 ...

  6. 数位dp的概念和模板

    基础篇 数位dp是一种计数用的dp,一般就是要统计一个区间[le,ri]内满足一些条件数的个数.所谓数位dp,字面意思就是在数位上进行dp咯.数位还算是比较好听的名字,数位的含义:一个数有个位.十位. ...

  7. 不要62(HDU-2089)(数位DP模板题)

    杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer). 杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍 ...

  8. 数位dp总结 之 从入门到模板

    基础篇 数位dp是一种计数用的dp,一般就是要统计一个区间[le,ri]内满足一些条件数的个数.所谓数位dp,字面意思就是在数位上进行dp咯.数位还算是比较好听的名字,数位的含义:一个数有个位.十位. ...

  9. HDU 3555 Bomb(数位DP模板啊两种形式)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555 Problem Description The counter-terrorists found ...

最新文章

  1. 独家 | 提升API设计技能的22个最佳实践(附链接)
  2. 使用Office组件读取Excel,引用Microsoft.Office.Interop.Excel出现的问题
  3. 使用netsh命令来管理IP安全策略(详细介绍)
  4. [zz]volatile
  5. Diffie Hellman密钥交换
  6. [密码学基础][每个信息安全博士生应该知道的52件事][Bristol52]45.描述一些对抗RSA侧信道攻击的防御方法
  7. 4am永远 鼠标按键设置_4AM称霸PCL和PEL 绝地求生与和平精英的双端冠军 | 电玩巴士...
  8. OpenVINO 2019 R2.0 Custom Layer Implementation for linux(2)
  9. 从零开始用Python搭建超级简单的点击率预估模型
  10. 自动驾驶路径规划论文解析(4)
  11. 关于使用cadence建pad
  12. 吴恩达机器学习(一)单变量线性回归(假设函数、代价函数、梯度下降)
  13. 解三对角矩阵以及循环三对角矩阵方程的数值计算方法
  14. 服务器虚拟化2种架构,服务器虚拟化常用架构详解
  15. 垃圾邮件过滤python_手把手教你用Python 和 Scikit-learn 实现垃圾邮件过滤
  16. 论文笔记:Bridging Textual and Tabular Data for Cross-Domain Text-to-SQL Semantic Parsing
  17. Zigbee学习——基本概念和串口
  18. 国内BLDC电机控制方案目前存在什么痛点?
  19. 全球及中国航空机电开关行业重点领域需求及未来发展展望报告2022-2028年
  20. CDH6.3.2环境搭建

热门文章

  1. springBoot中自定义的yml文件引用的方式
  2. c语言 将url图片存到本地_python爬虫:爬取男生喜欢的图片
  3. matlab的exec程序,C++调用Matlab画图的一段程序
  4. php求完数,php算法:求完全数 | 学步园
  5. 计算机接口控制采集时序图,自动站实时数据质量控制
  6. mysql uroot e_批量 kill mysql 连接
  7. C 之父:精通C 很难,但你一天之内就能学习使用C
  8. 16.04编译android 7.0,ubuntu16.04 编译Android5.1报错
  9. oracle yyyy和yy,Oracle PL / SQL:SYSDATE与’DD-MMM-YY’的区别?
  10. matlabif语句怎么用_公益心 码客行(2)—— 简单语句