![](https://img-blog.csdnimg.cn/20201014180756927.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
数位dp
1
1E6
这个作者很懒,什么都没留下…
展开
-
数位dp笔记(详解+例题+解析)
数位dp笔记简单介绍数位:把一个数字按照个、十、百、千等等一位一位地拆开,关注它每一位上的数字。如果拆的是十进制数,那么每一位数字都是 0~9,其他进制可类比十进制。数位 DP:用来解决一类特定问题,这种问题比较好辨认,一般具有这几个特征: 1.要求统计满足一定条件的数的数量(即,最终目的为计数); 2.这些条件经过转化后可以使用「数位」的思想去理解和判断; 3.输入会提供一个数字区间(有时也只提供上界)来作为统计的限制; 4.上界很大(比如 1018),暴力枚举验证会超时。考虑人类原创 2021-11-12 21:00:17 · 1916 阅读 · 0 评论 -
[SPOJ - BALNUM] Balanced Numbers (数位dp经典类型)
[SPOJ - BALNUM] Balanced Numbers题目链接大致题意:求区间内,一个数的数位上每个奇数出现偶数次,每个偶数出现奇数次,这样数的个数解题思路:这道题感觉用不到常规的参数,例如pre(上一个数字),sum(每一位数字的和)等等…因此我们需要想办法把奇数和偶数的出现次数存起来,最后进行判断状压是不是可以呢?一共只有0~9十种数字,用三进制表示,0表示没出现过,1表示出现了奇数次,2表示出现了偶数次,而且310=59049,内存不超,可以敲为了方便,写两个函数,一个原创 2021-11-04 14:58:02 · 101 阅读 · 0 评论 -
[HDU - 4734] F(x) (数位dp)
[HDU - 4734] F(x)题目链接大致题意:f(x) = a(n)*2(n-1)+a(n-1)*2(n-2)+…a(2)*21+a(1)*20,( a(i)表示十进制数x中第i位的数字 )给出a,b,求出0~b有多少个不大于f(a)的数解题思路:首先先计算出f(a)的值然后将f(a)的值作为初始值,每次递归减去每一位对应的数值,只要递归到最低位时sum>=0,说明满足条件,累加结果AC代码:#include <bits/stdc++.h>using n原创 2021-11-03 20:49:21 · 95 阅读 · 0 评论 -
[HDU - 3652] B-number (数位dp入门)
[HDU - 3652] B-number题目链接大致题意:统计区间 [1,n] 中含有 ‘13’ 且模 13 为 0 的数字有多少个解题思路:模13等于0,老套路了,利用参数yu判断即可含有13这个条件利用flag标记就行,flag=0表示没有13,flag=1表示前一个数字是1,flag=2表示包含13这类题做的多了就会打了AC代码:#include <bits/stdc++.h>using namespace std;typedef long long ll原创 2021-11-03 20:32:44 · 167 阅读 · 0 评论 -
[HDU - 3709] Balanced Number (数位dp)
[HDU - 3709] Balanced Number题目链接大致题意:给定区间[a,b],求区间内平衡数的个数平衡数:即有一位做平衡点,左右两边数字的力矩相等解题思路:判断力矩是否相等,需要参数sum记录力矩情况,初始为0,递归到最低位还是0,说明左右两边力矩相等对于平衡点,需要进行枚举统计所以枚举的平衡点,每一次dfs结果会加上固定平衡点满足条件的数字个数除此之外,数字0也是满足的,但是00,000,0000不满足,所以最终答案res-len+1AC代码:#include原创 2021-11-03 18:26:17 · 91 阅读 · 0 评论 -
[POJ - 3252] Round Numbers (数位dp入门题)
[POJ - 3252] Round Numbers题目链接大致题意:统计区间[l,r]内的数二进制形式下,0的个数>=1的个数的数的个数解题思路:入门题因为要统计0的个数和1的个数,因此需要两个参数num0,num1分别表示二进制中0和1的个数递归到最低位是,判断num0是否>=num1即可,累加结果AC代码:#include <bits/stdc++.h>using namespace std;typedef long long ll;const原创 2021-11-03 18:03:25 · 110 阅读 · 0 评论 -
[codeforces] Beautiful numbers (数位dp好题)
[codeforces] Beautiful numbers题目链接大致题意:统计区间[l,r]内的数能整除它所有位上的非零整数的个数解题思路:如果一个数能整除它所有位上的非零整数,那么它一定可以整除它所有位上非零整数的最小公倍数因此我们需要参数prelcm,用来记录前面数的最小公倍数但是我们不可能记录这个数字本事是多少,因为它太大了,我们需要把它缩小通过计算可以知道1~9的最小公倍数是2520,假设数字x可以整除它的所有位上的非零整数那么,x%lcm(a[i])=0然后2520%l原创 2021-11-03 16:52:34 · 149 阅读 · 0 评论 -
[LibreOJ - 2215] 方伯伯的商场之旅 (数位dp)
[LibreOJ - 2215] 方伯伯的商场之旅题目链接大致题意:给出l,r,k,求将l与r之间的数进行x操作的最小代价.x操作指将一个数转化为k进制,表示有几堆石块,每堆石块恰有该数位上的数个石子,相邻两堆距离为1,将它们并成一堆,代价为石头数量*距离.解题思路:对于固定一个位置来说,代价我们可以求出来,但是怎么求出最小代价呢?思考ing…数位dp肯定是要对位数下刀!!!不要坐以待毙,先把固定第一位的代价求出来当我们把固定点从低位向高位转移时,可以发现,代价会加上左边的数字和,减原创 2021-11-03 08:35:31 · 86 阅读 · 0 评论 -
[黑暗爆炸 - 1799] self 同类分布 (数位dp)
[黑暗爆炸 - 1799] self 同类分布题目链接大致题意:统计区间[l,r]中各位数字之和能整除原数的数的个数解题思路:两个关键信息:各位数字之和 整除原数各位数字之和只需要参数sum统计即可,整除余数可以通过余数来判断但是我们只有递归到最低位才知道数字之和,但是余数需要从开始就确定模数才能进行递归,那怎么解决呢?我们发现最多只有18位,也就是说各位数字之和最大也就18*9,我们可以通过枚举模数mod,每次dp求出区间[l,r]各位数字之和等于模数,且余数等于0,就是整除原数的数字原创 2021-11-02 19:32:13 · 110 阅读 · 0 评论 -
[codeforces] Classy Numbers(数位dp)
[codeforces] Classy Numbers题目链接大致题意:统计区间[l,r]中,在十进制下表示,出现不超过三个非零数字的个数,例如4,200000,10203解题思路:cnt表示非零数字出现的次数,当cnt>3跳过即可所有能递归到最低位的均为合法情况状态方程:f[i][j] 表示第i位出现了j个非零数字的数字个数AC代码:#include <bits/stdc++.h>using namespace std;typedef long long l原创 2021-11-02 19:06:56 · 179 阅读 · 0 评论 -
[codeforces] Salazar Slytherin’s Locket (数位dp)
[codeforces] Salazar Slytherin’s Locket题目链接大致题意:统计区间[l,r]中,在b进制下每种0~b-1的数的个数都出现偶数次的个数,不包含前导零解题思路:因为涉及到数字0的计算,所以前导零的判断一定有然后我们思考,怎么统计0~b-1每一个数字是否出现了偶数次呢?状压!!!异或操作:相同为0,不同为1也就是说如果数字1异或偶数次数字1,结果不变,还是1所以我们可以用(1<<k)-1表示初始状态 二进制状压表示状态,根据枚举的数字i,通原创 2021-11-02 18:36:56 · 141 阅读 · 0 评论 -
[LibreOJ - 10166] 数字游戏 (数位dp入门题)
[LibreOJ - 10166] 数字游戏题目链接大致题意:统计区间内,取模数的个数取模数:这种数字必须满足各位数字之和 mod N 为 0解题思路:我们需要参数sum记录每一位数字和当递归到最低位时,判断sum是否可以对N取模即可,累加结果AC代码:#include <bits/stdc++.h>using namespace std;typedef long long ll;const int N = 30;int n;int a[N];ll f[N原创 2021-11-02 18:17:26 · 1512 阅读 · 0 评论 -
[LibreOJ - 10164] 数字游戏 (数位dp入门题)
[LibreOJ - 10164] 数字游戏题目链接大致题意:统计区间内,不降数的个数不降数:这种数字必须满足从左到右各位数字成小于等于的关系,如 123,446解题思路:我们只需要参数pre记录上一位的数字是多少在搜索枚举过程中,将i<pre的情况跳过即可 (i当前位枚举的数字是多少)AC代码:#include <bits/stdc++.h>using namespace std;typedef long long ll;const int N = 30原创 2021-11-02 18:05:42 · 1750 阅读 · 0 评论 -
[HDU - 3555] Bomb (数位dp入门题)
[HDU - 3555] Bomb题目链接大致题意:统计区间内,包含连续49的数字个数解题思路:对于包含49,需要参数pre记录前一位数字情况容斥原理,包含49的数字个数=总个数-不包含49的数字个数与 HDU - 2089 不要62 同类型状态方程:f[i][j]表示到第i位,前一位数字是否是4满足条件的数字个数AC代码:#include <bits/stdc++.h>using namespace std;typedef long long ll;con原创 2021-11-02 14:28:27 · 109 阅读 · 0 评论 -
[黑暗爆炸 - 1026] windy数 (数位dp)
[黑暗爆炸 - 1026] windy数题目链接大致题意:统计区间内,不含前导零且相邻两个数字之差至少为2的正整数的个数解题思路:与 HDU - 2089 不要62 同类型对于相邻数字之差至少为2,需要参数pre记录前一位数字情况题目明确不含前导零,因此前导零参数也必须有当zero=1(有前导零)时,相邻两个数字之差至少为2这个条件不需要成立,因为后一条件必须要有两个都不为前导零的真实数字存在两种成立情况写成zero || abs(pre - i) > 1当zero=0(没有前原创 2021-11-02 14:09:24 · 201 阅读 · 0 评论 -
[黑暗爆炸 - 1833] count 数字计数 (数位dp经典题)
[黑暗爆炸 - 1833] count 数字计数题目链接大致题意:给定两个正整数 a和b,求在[a,b]的所有整数中,每个数码(0~9)各出现了多少次解题思路:需要统计0的出现次数,所有必须要有参数前导零,因为前导零不计算为0的出现次数因为要计算0~9每一个数字的出现次数,所以我们对于每一个数字进行数位dp,找到区间[a,b]的所有整数中,数字i出现的次数既然需要枚举每一个数字,那么我们还需要参数dig表示哪一个数字,除此之外,还需要参数sum,表示数字i出现的次数总和状态方程f[N]原创 2021-11-02 11:07:29 · 189 阅读 · 0 评论 -
Find 3-friendly Integers (数位dp)
Find 3-friendly Integers题目链接大致题意:求出区间[l,r]内有多少个数字满足:存在 0(不包括前导零);存在3;连续十进制位数加和整除3解题思路:思维题,也可以用数位dp,这里讲一下数位dp的做法状态表示:f[20][2][2][2] 表示第pos位,余数是否为1,余数是否为2,是否能整除3的个数分析:数位dp判断是否存在0或者3很好写,但是怎么判断十进制位中连续位上的数加和能整除3我们用余数来表示状态,通过!(zero && i == 0)判断,原创 2021-07-19 10:00:10 · 121 阅读 · 0 评论 -
Digit Products(数位dp)
Digit Products题目链接大致题意:给出两个整数n,m,要求出从1到n的数中,求满足每一位上的数字乘积小于m的数字个数解题思路:很容易想到数位dp,数据1e18状态表示:map<ll,ll>f[30][2][2] 表示第i位,是否有限制,是否有前导零,乘积是x的个数我们不能直接开四维,因为乘积太大,存不下然后就是改改模板就可以了AC代码:#include <bits/stdc++.h>#define rep(i, n) for (int i = 1原创 2021-07-05 18:05:24 · 324 阅读 · 3 评论 -
Sum of Log (数位dp)
Sum of Log题目链接大致题意:略~解题思路:状态表示:f[N][2][2] 表示二进制位数最长是i,x是否到达上限,y是否到达上限得方案数分析:log2(i+j)+1 就是求(i+j)的二进制位,我们可以通过枚举二进制位数,求满足(i&j)==0的方案数,数位dp求即可补充:还是自己多想想吧,我也不知道该写啥了AC代码:#include <bits/stdc++.h>#define rep(i, n) for (int i = 1; i <= (n原创 2021-06-23 18:32:19 · 163 阅读 · 0 评论 -
牛客 和与或 数位dp
和与或题目链接大致题意:给出序列R,求满足0<=A[i]<=R[i] 且A[0]+A[1]+…+A[N-1]=A[0] or A[1]… or A[N-1] 的序列个数,答案对1e9+9取模解题思路:定义sum=A[0]+A[1]+…+A[N-1],转化为二进制后满足A[0] or A[1]… or A[N-1],表示将A[0] A[1]… A[N-1]转化为二进制后,sum二进制上的1只能来自其中的一个A[i],且该位上不能有超过两个1出现,以此为基础考虑数位dp状态表示: f[i原创 2021-05-14 17:39:19 · 110 阅读 · 0 评论 -
kuangbin专题十五 数位dp
文章目录Beautiful numbers--CodeForces - 55DXHXJ's LIS--HDU - 4352不要62--HDU - 2089Bomb--HDU - 3555Round Numbers--POJ - 3252Balanced Number--HDU - 3709B-number--HDU - 3652F(x)--HDU - 4734吉哥系列故事——恨7不成妻--HDU - 4507Balanced Numbers--SPOJ - BALNUMBeautiful numbers–原创 2021-04-19 20:05:47 · 161 阅读 · 0 评论 -
17867 明七暗七 牛客(二分+数位dp)
题目链接: 明七暗七大致题意:找到数字m之后第n个含有7或7的倍数的数字解题思路:二分+数位dp数位dp找1到n有多少个数字是含有7或7的倍数的数字,然后二分在m和1e18中找答案AC代码:#include <bits/stdc++.h>using namespace std;typedef long long ll;ll n, m;int a[20];ll f[20][2][7]; //位数 是否有7 余数ll dfs(int pos, int seven, i原创 2021-01-31 20:52:26 · 252 阅读 · 0 评论 -
17385 Beautiful Numbers 牛客(数位dp)
题目链接: Beautiful Numbers大致题意:求出1到n之间有多少个数是他本身对位数总和取余为0解题思路:数位dp数据是1e12,位数总和也就12*9,枚举位数和,累加结果AC代码:#include <bits/stdc++.h>using namespace std;typedef long long ll;ll n;int sum;ll f[15][120][120]; //位数 总和 余数int num[15];ll dfs(int pos, i原创 2021-01-31 19:38:06 · 105 阅读 · 0 评论 -
Bear and Compressing(数位dp)
题目链接: Bear and Compressing大致题意:给出q组数据,每组数据有一个长度为2的字符串ai和一个字符bi,表示字符串ai可以转化成bi,现在限定一段长度为n的字符串,当它最前的两个字符和ai可以匹配,则可以转换为bi,转换次数不限。现在问有多少段这样的字符串最终可以转化成’a’。解题思路:数位dpf[i][j][flag]表示处理到第i位,前一位是j,flag表示是否合法AC代码:#include <bits/stdc++.h>using namesp原创 2021-01-14 15:26:01 · 130 阅读 · 0 评论 -
HDU - 4734 F(x) (数位dp)
题目链接: F(x)大致题意:f(x) = a(n)*2(n-1)+a(n-1)*2(n-2)+…a(2)*2+a(1)*1,a(i)表示十进制数x中第i位的数字。给出a,b,求出0~b有多少个不大于f(a)的数解题思路:每组样例dp的值不一定相同 如 1 10 f[0][0] = 1; 而 2 100 f[0][0] = 2,因此每次都需要初始化,会导致超时所以让f[i][j]表示第i位不大于j的个数AC代码:#include<iostream>#include<原创 2020-12-06 20:23:08 · 60 阅读 · 0 评论 -
HDU - 3709 Balanced Number(数位dp)
题目链接: Balanced Number大致题意:平衡数是以这个数字的某个位作为支点,另外两边的数字大小乘以力矩之和相等。求区间内的平衡树个数解题思路:f[pos][x][state]表示第pos位,支点是第x位,当前力矩之和是state的个数转移方程:f[pos][x][state]=f[pos-1][x][state+i*(pos-x)]1.枚举支点2.支点确定后,开始填数,利用记忆化搜索搜出所有可能数的情况3.ans累加上当前知点力矩为0的数字个数两个题代码有点类似,可以看一下原创 2020-11-29 00:00:19 · 92 阅读 · 0 评论 -
HDU - 3555 Bomb(数位dp)
题目链接: Bomb大致题意:统计从1到n区间内含有49(字串)的数字个数解题思路:f[i][j]:长度为i的数的第j种状态f[i][0]:长度为i但是不包含49的方案数f[i][1]:长度为i且不含49但是以9开头的数字的方案数f[i][2]:长度为i且包含49的方案数状态转移:f[i][0]+=f[i-1][0]*10-f[i-1][0] 加上所有不含49的情况-第i位是9的情况f[i][1] += f[i - 1][0] 第i位是9加上其他位不含49的情况f[i][原创 2020-11-28 21:00:54 · 97 阅读 · 0 评论 -
HDU - 4352 XHXJ‘s LIS(数位dp+状态压缩LIS)
题目链接: XHXJ’s LIS大致题意:又臭又长的题面求给定区间内长度为k的最长上升子序列的个数解题思路:涉及数位dp,状态压缩,LIS1.LIS O(nlogn)算法定义f[len],初始len=0,a[]={4,2,6,3,1,5};if(a[i]>f[len]) ++len,f[len]=a[i];else 从1~len中找到一个位置k,满足f[k-1]<a[i]<f[k],令f[k]=a[i];总的来说就是找到第一个比自己大或相等的数,将它删除,把自己放原创 2020-11-28 18:29:04 · 128 阅读 · 0 评论 -
[HDU-2089] 不要62(数位dp模板题)
题目链接: 不要62大致题意:给一个区间,统计区间中不含4和62的数字个数解题思路:对于1e9的数据,可以用数位dp来做对于区间求个数,通常套路是dp®-dp(l-1)求[l,r]区间的数字个数f[i][j] 表示填到第i位,当第i位填j的时候有多少种合适的数字分解每一位,从最高位开始判断,累加上所有满足条件的数字个数特判一下0AC代码:#include<iostream>#include<algorithm>#include<cstring>原创 2020-11-27 23:10:16 · 392 阅读 · 0 评论