转载:数位DP模板

//    pos    = 当前处理的位置(一般从高位到低位)
 2 //    pre    = 上一个位的数字(更高的那一位)
 3 //    status = 要达到的状态,如果为1则可以认为找到了答案,到时候用来返回,
 4 //            给计数器+1。
 5 //    limit  = 是否受限,也即当前处理这位能否随便取值。如567,当前处理6这位,
 6 //            如果前面取的是4,则当前这位可以取0-9。如果前面取的5,那么当前
 7 //            这位就不能随便取,不然会超出这个数的范围,所以如果前面取5的
 8 //            话此时的limit=1,也就是说当前只可以取0-6。
 9 //
10 //    用DP数组保存这三个状态是因为往后转移的时候会遇到很多重复的情况。
11 int    dfs(int pos,int pre,int status,int limit)
12 {
13     //已结搜到尽头,返回"是否找到了答案"这个状态。
14     if(pos < 1)
15         return    status;
16
17     //DP里保存的是完整的,也即不受限的答案,所以如果满足的话,可以直接返回。
18     if(!limit && DP[pos][pre][status] != -1)
19         return    DP[pos][pre][status];
20
21     int    end = limit ? DIG[pos] : 9;
22     int    ret = 0;
23
24     //往下搜的状态表示的很巧妙,status用||是因为如果前面找到了答案那么后面
25     //还有没有答案都无所谓了。而limti用&&是因为只有前面受限、当前受限才能
26     //推出下一步也受限,比如567,如果是46X的情况,虽然6已经到尽头,但是后面的
27     //个位仍然可以随便取,因为百位没受限,所以如果个位要受限,那么前面必须是56。
28     //
29     //这里用"不要49"一题来做例子。
30     for(int i = 0;i <= end;i ++)
31         ret += dfs(pos - 1,i,status || (pre == 4 && i == 9),limit && (i == end));
32
33     //DP里保存完整的、取到尽头的数据
34     if(!limit)
35         DP[pos][pre][status] = ret;
36
37     return    ret;
38 }

转载自:http://www.cnblogs.com/xz816111/p/4809913.html
时间: 2024-10-21 04:16:33

转载:数位DP模板的相关文章

POJ 3286 How many 0&#39;s(数位DP模板)

题目链接:http://poj.org/problem?id=3286 题目大意: 输入n,m,求[n,m]的所有数字中,0出现的总数是多少,前导零不算. 解题思路: 模板题,设dp[pos][num],pos为数位,num为当前0的数目,然后套数位DP模板即可. 还有之前的一些思考: 关于数位DP求0时,dp下标记录num有什么作用,num不是与后面的0的个数无关吗?是的,在(!limit&&!lead)的情况下,前面有多少0是不影响后面可以出现多少0的.但是,比如说dp[pos][nu

数位dp模板 [dp][数位dp]

现在才想到要学数位dp,我是不是很弱 答案是肯定的 以一道自己瞎掰的题为模板 1 //题: 2 //输入数字n 3 //从0枚举到n,计算这n+1个数中含有两位数a的数的个数 4 //如12930含有两位数93 5 #include<cstdio> 6 #include<cstring> 7 #include<iostream> 8 using namespace std; 9 10 int n,m=0,a,g1,g2; 11 int dp[10][10][2],lim

51nod 1009 - 数字1的数量 - [数位DP][模板的应用以及解释]

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1009 基准时间限制:1 秒 空间限制:131072 KB 给定一个十进制正整数N,写下从1开始,到N的所有正数,计算出其中出现所有1的个数. 例如:n = 12,包含了5个1.1,10,12共包含3个1,11包含2个1,总共5个1. Input 输入N(1 <= N <= 10^9) Output 输出包含1的个数 Input示例 12 Output示例

HDU - 4722 Good Numbers 【找规律 or 数位dp模板】

If we sum up every digit of a number and the result can be exactly divided by 10, we say this number is a good number. You are required to count the number of good numbers in the range from A to B, inclusive. InputThe first line has a number T (T <=

数位dp模板

1 //HDU - 5787为例 2 //求区间[L,R]内,任意相邻k位(如果位数不足k,就是全部的数位)没有两两相同的数位的数的个数 3 LL l,r; 4 int k; 5 int num[20]; 6 LL dp[20][10010][5]; 7 //pos表示当前处理的位置(一般从高到低) 8 //limit是限制当前这位能否随便取,即决定top=num[pos]或top=9. 9 //非limit的状态可以记录起来,因为此时pos后面的数字都可以随便取,所以状态是一样的. 10 //

数位DP模板详解

1 // pos = 当前处理的位置(一般从高位到低位) 2 // pre = 上一个位的数字(更高的那一位) 3 // status = 要达到的状态,如果为1则可以认为找到了答案,到时候用来返回, 4 // 给计数器+1. 5 // limit = 是否受限,也即当前处理这位能否随便取值.如567,当前处理6这位, 6 // 如果前面取的是4,则当前这位可以取0-9.如果前面取的5,那么当前 7 // 这位就不能随便取,不然会超出这个数的范围,所以如果前面取5的 8 // 话此时的limit

不要62(数位dp模板题)

AC_Code: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <cmath> 6 #include <queue> 7 #include <stack> 8 #include <vector> 9 #include <set> 10 #include <

hdu 2089 不要62 【数位DP】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089 数位DP模板题,测试板子 代码: #include <stdio.h> #include <ctime> #include <math.h> #include <limits.h> #include <complex> #include <string> #include <functional> #include &l

BZOJ 1833 数字计数(数位DP)

经典数位DP模板题. # include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector> # include <queue> # include <stack> # include <map> # include <set> # include <cmath>