数位dp

nowcoder A hard problem /// 数位DP

一曲冷凌霜 提交于 2020-02-21 04:33:46
题目大意: 称一个数x的各个数位之和为f(x) 求区间L R之间 有多少个数x%f(x)==0 #include <bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f #define LL long long #define inc(i,j,k) for(int i=j;i<=k;i++) #define dec(i,j,k) for(int i=j;i>=k;i--) #define gcd(i,j) __gcd(i,j) #define mem(i,j) memset(i,j,sizeof(i)) const int N=2e5+5; int rd, dfn[2][15][50][50]; int fx, tot, a[15]; LL dp[2][15][50][50]; // dp[f][w][s][m] // f为1说明不是上界 此时为第w位数 // 剩下的数位总和为s 此时的数位总和%f(x)为m LL DFS(int f,int w,int s,int m) { if(w==0) return (s==0&&m==0); // 所有位都枚举过了则w=0 // 所有数位总和为fx则s=0 // x%fx==0则m=0 if(dfn[f][w][s][m]==rd) return dp[f][w][s][m]

HDU 4734 F(x)(数位DP)

会有一股神秘感。 提交于 2020-02-18 04:13:11
For a decimal number x with n digits (A n A n-1 A n-2 ... A 2 A 1 ), we define its weight as F(x) = A n * 2 n-1 + A n-1 * 2 n-2 + ... + A 2 * 2 + A 1 * 1. Now you are given two numbers A and B, please calculate how many numbers are there between 0 and B, inclusive, whose weight is no more than F(A). Input The first line has a number T (T <= 10000) , indicating the number of test cases. For each test case, there are two numbers A and B (0 <= A,B < 10 9 ) Output For every case,you should output "Case #t: " at first, without quotes. The t is the case number starting from 1. Then output the answer

HDOJ3652解题报告【数位DP】

一曲冷凌霜 提交于 2020-02-17 07:04:04
题目地址:   http://acm.hdu.edu.cn/showproblem.php?pid=3652 题目概述:   给出一个数n,求出1~n中所有包含“13”并且是13的倍数的数的个数。例如13满足条件,而143虽然是13的倍数,不过不包含“13”,所以不满足条件。 大致思路:   这种类型的题应该很容易看出是数位DP,这里设f[i,j,k,l]表示i位数当前位是j,这个数mod13=k的情况,l=1表示包含“13”,l=0表示不包含。   转移的话详见代码。 代码: #include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <vector> #include <ctime> #include <map> #include <stack> #include <queue> #include <cstring> #include <algorithm> using namespace std; #define sacnf scanf #define scnaf scanf #define scanfi(x) scanf("%d",&x) #define scanfd(x) scanf("%lf",&x) #define scanfl(x) scanf("%lld",

寒假日志 6

六眼飞鱼酱① 提交于 2020-02-16 03:29:47
这几天比赛有点多,牛客训练赛,codeforce,补题都补不过来了快。。。不过,补题收获的确实比较多,但是也比较耗费时间。。。 这几天和往常一样睡懒觉,昨晚的codeforce B和C都Wa了两发,脑子转的有点慢。。。D题最后也没思路,最后倒也是加了点分,现在还未出来题解。今天的牛客和往常一样,感觉自己出的差不多了就去玩了。。。这几场是越来越难了,今天还有cf,后天还有cf,后天还有牛客。题真补不过来了,先记到小本本上,嘿嘿,以后再补(谁知道以后是多久) 上回AtcoderE题数位DP还没补上,牛3的数位DP也还没补上。。。。学不明白呜呜呜。 老师布置的专题还没开始刷,只能干着急。干着急也没用,立马去学! 寒假就这样在我慵懒的手指下,舒服的被窝里 悄悄溜走了,来日方长都是骗人的,滚去补题了。 来源: CSDN 作者: 冷血怪兽 链接: https://blog.csdn.net/qq_43408238/article/details/104303215

Hdu 4734-F(x) 数位dp

我只是一个虾纸丫 提交于 2020-02-15 15:33:59
题目: http://acm.hdu.edu.cn/showproblem.php?pid=4734 F(x) Time Limit: 1000/500 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3347 Accepted Submission(s): 1258 Problem Description For a decimal number x with n digits (A n A n-1 A n-2 ... A 2 A 1 ), we define its weight as F(x) = A n * 2 n-1 + A n-1 * 2 n-2 + ... + A 2 * 2 + A 1 * 1. Now you are given two numbers A and B, please calculate how many numbers are there between 0 and B, inclusive, whose weight is no more than F(A). Input The first line has a number T (T <= 10000) , indicating the number of test cases.

HDU 4734 F(x) (数位DP)

痞子三分冷 提交于 2020-02-15 05:49:07
F(x) Time Limit: 1000/500 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 382 Accepted Submission(s): 137 Problem Description For a decimal number x with n digits (A n A n-1 A n-2 ... A 2 A 1 ), we define its weight as F(x) = A n * 2 n-1 + A n-1 * 2 n-2 + ... + A 2 * 2 + A 1 * 1. Now you are given two numbers A and B, please calculate how many numbers are there between 0 and B, inclusive, whose weight is no more than F(A). Input The first line has a number T (T <= 10000) , indicating the number of test cases. For each test case, there are two numbers A and B (0

[HDU4734] F(x)(数位dp+优化)

会有一股神秘感。 提交于 2020-02-14 23:10:13
>传送门< 题意: 对于一个有 n 位(这 n 位从高位到低位分别是 A n , A n-1 , A n-2 ... A 2 , A 1 )的十进制数,我们定义它的权值 F(x)=A n *2 n-1 + A n-1 *2 n-2 + ... + A 2 *2 + A 1 *1. 现在给你两个数 A , B ,请计算 [0,B] 范围内有多少个权值<= F(A) 的数 思路: (这个下面文字是有点多,可能是我太弱了,在刚开始学的时候只有这样我才能理解QAQ~) 其实 F(x) 只是给每一个数位带上一个权值 v = 2^(p-1) , F(x) 最大是值不会超过5000,我们完全可以抛开权值来思考,写代码的时候再加上权值即可,这样思考和写草稿之类的会方便很多,不考虑每一位的权值的话即是数位的前缀和。 很容易想到一个 dp 式是 dp[pos][sum] ;表示当前在第 pos 位,前缀和为 sum 的答案,快速把数位 dp 敲完,交上去,然后会发现 TLE 掉了,这题的时限只有500ms, TLE 的原因是什么呢,就是 记忆化不够彻底 。 在做数位 dp 入门题 不要62 的时候可能有些人会注意到, dp 数组只需要初始化一次即可,这是因为不要62题意中是不包含4和连续的62的数的个数,这里的条件是一个数本身的性质,也就是说,一个数有没有4或者连续的62和你输入的 [l,r]

数位dp入门学习之路(正常枚举“过渡到”dfs枚举)

二次信任 提交于 2020-02-12 14:57:24
前言 :数位dp就是换一种穷举方式。额......我第一次看这句话也懵,哎,资深学渣,来记个笔记先。 正常枚举“过渡到”dfs枚举(这里暂时是穷举的数为:1、10、100、1000、10000....,要穷举任意数在后面给出) 其实有些兄弟用了递推关系来做这类题,但个人感觉那种解题方式还是太花时间了。。。。。。。。。。 正常枚举: #include <iostream> #include <cstdio> #define ll long long using namespace std; int main() { for (int i = 0; i <= 1000) { printf("%d\n", i); } return 0; } 结果:略(看数学答案也是这样) dfs枚举:注意pos参数的意思是枚举到当前数字的位数。dfs是从数字的高位往低位枚举(当数字的枚举是也是从小到大的)。num用于记录当前枚举的数字 dfs(pos=0, num); 表示只枚举长度为1的数字,最大数为9 dfs(pos=1, num); 表示只枚举长度为2的数字,最大数为99 dfs(pos=2, num); 表示只枚举长度为3的数字,最大数为999 最好自己动手测一下其他结果,不要光靠脑袋想,除非...........哈哈 #include <iostream> #include <cstdio>

hdu3555(数位dp)

不羁岁月 提交于 2020-02-12 02:46:47
题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=3555 题意:求区间[a,b]内包含有'49'的数的总个数。 分析:dp[pos][0]表示到第pos位没有包含49,后面1~pos-1位任意填时的总个数,dp[pos][1]表示到第pos位时前一位刚好是'4',后面任意填时的总个数,dp[pos][2]表示已经包含49后面任意填的总个数。。。 #include <cstdio> #include <cstring> #include <string> #include <cmath> #include <iostream> #include <algorithm> #include <queue> #include <cstdlib> #include <stack> #include <vector> #include <set> #include <map> #define LL long long #define mod 10007 #define inf 0x3f3f3f3f #define N 100010 #define FILL(a,b) (memset(a,b,sizeof(a))) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace

算法学习:数位DP

允我心安 提交于 2020-02-11 17:09:23
【解决问题】 一个极大的多位数字中,存在某种特殊情况出现多少次 通过记忆化和动态规划的方法,将之前的情况数记录下来,在计算其他情况的时候,通过状态的转移相互利用 【模板】 【题意】求1~n之间有多少个数又含有13又能被13整除,(1<=n<=1e9) 【代码】 #include<cstdio> #include<cstring> #define MAXN 20 int dp[MAXN][MAXN][10]; int maxx[MAXN]; //maxx记录整个数字的上限 //len 表示当前枚举的数字长度 //mod 表示状态之一,现在这个长度对16取余的结果 //stu 状态之一,当前的数字是否存在 //lim 状态之一,前面的数字是否达到上限,因为枚举的情况在前面没有达到的话,后面的是可以任取的 // 而如果达到的话,就需要考虑数字的取值范围了 int Geta(int len,int mod,int stu,bool lim) { //从后往前开始枚举数字的情况 if(len==0) //当所有位置上的数字列举完成之后 return mod==0&&stu==2; //返回存在的情况 if(!lim && dp[len][mod][stu]) return dp[len][mod][stu]; //max 表示需要遍历到的最大的数字 int cnt=0,max=lim