看到诸位神牛的代码和Blog,我也来班门弄斧学一下 数位dp
Step0:找木板和资料
向ftiasch 和 edward_mj (窃笑,师父们T_T)求了资料,得到一个好板子——BUPT 某神的Blog
Step1:撸水题
HDU 2089 直接暴力就可以,不过还是老老实实地数位dp一把,基本是板子题目。
HDU 3555 同上的数位DP
UESTC 1307 前导0 建立状态原来还可以用11来代替啊。这样的话每次Quest dfs一次即可。
POJ 3252 f[pos][s][zero][one]
Step2:撸中等题
1.hdu 4507
http://acm.hdu.edu.cn/showproblem.php?pid=4507
Tecent 2012.3.21 C 题
题目描述
求[l , r] 中
如果一个整数符合下面3个条件之一,那么我们就说这个整数和7有关——
1、整数中某一位是7;
2、整数的每一位加起来的和是7的整数倍;
3、这个整数是7的整数倍;
现在问题来了:吉哥想知道在一定区间内和7无关的数字的平方和。
1、整数中某一位是7;
2、整数的每一位加起来的和是7的整数倍;
3、这个整数是7的整数倍;
现在问题来了:吉哥想知道在一定区间内和7无关的数字的平方和。
方法:
肯定是数位dp
必须这个满足减法——[l , r] = [0 , r] - [0 , l - 1]
我的算法是算相反的——即和数7有关的平方和,然后用1/6 * n * (n + 1) * (2n + 1) 来减一下
首先确定状态 —— dp[枚举位数][是否含有7][个数的和%7][这个数%7]
其次是维护:
1、个数
2、和 (由个数算出
3、平方和(由个数和 和 算出
首先说个数算法:
这就是一个最裸的数位dp,贴个模板就能做了 。。模板含义见资料
再说和的做法:(这里很容易错啊。。。)
在枚举第 i 位 是 d 的时候,算出 i - 1 位之后的个数 has ,那么这个d 就出现了 has 次,于是就要统计 d * 10的幂 * has 。
最后说平方和的算法:(卧槽这里写挂了好久好么。。。)
还是枚举第 i 位 是 d 的时候。我们看跟后面的关系。假设这个数是 dxxxxxxx(后面一大堆数字) 。假设这个数字是 d * 10的幂(设为 x) + y(后面一大堆数字),那么我们就是要计算(x + y)^2。 拆开来就是 x ^ 2 + 2xy + y ^ 2 。 首先 y ^ 2 在后面我们已经算过了,直接 搜索深度+1就可以计算,2xy 的话需要用 2 * x * (出现次数