数位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  //pre表示上一位的数字或是上一个状态的数字
11  //dig是表示目前最多几位数字相邻数字互不相同。
12 LL dfs(int pos,int limit,int pre,int dig)
13 {
14
15     LL res=0;
16     if(pos<0)return 1;
17     if(!limit&&dp[pos][pre][dig]!=-1)return dp[pos][pre][dig];
18     int top=limit?num[pos]:9;       //---------------------只需根据题意修改for循环的语句即可------------------------------
19     for(int i=0;i<=top;i++)
20     {
21         int j;
22         int s=pre;
23         for(j=0;j<dig;j++)
24         {
25             if(s%10==i)break;
26             else s/=10;
27         }
28         if(j!=dig)continue;
29         if(i==0&&dig==0)res+=dfs(pos-1,limit&&(i==num[pos]),pre,dig);
30         res+=dfs(pos-1,limit&&(i==num[pos]),(pre%1000)*10+i,min(dig+1,k-1));
31     }       //--------------------------------------------------------------------------------
32     if(!limit)dp[pos][pre][dig]=res;
33     return res;
34 }
35 LL solve(LL n)
36 {
37     int cnt=0;
38     mt(dp,-1);
39     while(n)
40     {
41         num[cnt++]=n%10;
42         n/=10;
43     }
44     return dfs(cnt-1,1,0,0);
45 }
46 int main()
47 {
48 #ifdef Local
49     freopen("data.txt","r",stdin);
50 #endif
51     ios::sync_with_stdio(false);
52     cin.tie(0);
53     while(cin>>l>>r>>k)
54     {
55         cout<<solve(r)-solve(l-1)<<endl;
56     }
57     return 0;
58 #ifdef Local
59     cerr << "time: " << (LL) clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
60 #endif
61 }
时间: 2024-10-25 05:16:36

数位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模板

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

数位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 <

BZOJ 1833 数字计数(数位DP)

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

hdu 5179 数位dp

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5179 beautiful number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 198    Accepted Submission(s): 116 Problem Description Let A=∑ni=1ai?10n?i(1