BZOJ 1799 浅谈数位动态规划再进阶
2017-09-22 08:59
316 查看
世界真的很大
感觉对于数位动态规划的计数问题还是有点眉目了
起码基本上模板的感觉是有了
剩下的就是状态设计的问题,设计怎么样的状态可以让搜索时得以保存?
开始研究。。
看题先:
description:
给出a,b,求出[a,b]中各位数字之和能整除原数的数的个数。
input:
10 19
output:
3
一看到这道题就直接想dfs
由于自己被什么什么整除,肯定DFS的时候要保存一个每一位的mod数,然后又要数位和,那就保存一个数位和
然后DFs很快就出来了
dnt dfs(int pos,int sum,int val,int lim)
sum代表数位和,val代表mod数
但忽然发现mod的数是数位和,不唯一,没法每次保存,而且在数位和本身算出来之前,没法mod
那就改变状态,val代表这个数是什么,在最后一位的时候判断能不能整除
那么这时大暴力搜索已经可以写出来了,现在再套上一个记忆化的DP数组就是数位DP了
考虑设计DP的状态,这个一般是根据dfs的参数来的,f(i,j,k)
表示数位为i,前几位和为j,val为k的答案
好像不大对。。
val保存的是前几位的状态的答案,也就是说,两次DFSval相同,当前仅当DFS枚举的前几位全部相同才行
而DFS每个数只会枚举一次。。这和暴力没什么区别。。
考虑为什么数位DP能够优化,是因为他提前记录了现在需要继续转移的“后继”状态,相当于是后几位的答案,在多次访问后继状态时实行时间的优化
但是val恰恰是指前几位的数是什么。。跟后继不沾边儿
考虑为什么val必须要保存前几位的数是什么,因为不同的数的mod数不同,没法单单记录一个整除的余数来转移,也就是说,问题出在不同的数的数位和不同,导致mod的数不同,没法记录一个公共状态
怎么办呢
每个数的mod数不同,就没法保持当前状态的“后继”状态的答案,这的却是个问题
但是反过来说,如果mod数确定,不就可以保存后继状态了吗?
看一下题目,这个mod的数究竟是什么,原来是数位和
10^18的范围,就是说有18位数位,考虑每一位最大都是9,数位和最多不过 【162】
嗯~
好像思路显而易见了
我们考虑去枚举这样的数位和,不过枚举162次而已
问题就转化成了,数位和为i,且被i整除的数有多少
而这样一来,每次DFS时mod数相同,就可以递归mod的余数了,而一个余数加上后继的sum,表示的就是一堆后继的状态
和之前的f数组只会访问一次不同,这个可是多次访问的,记忆化成功
完整代码:
#include<stdio.h> #include<iostream> #include<cstring> using namespace std; typedef long long dnt; dnt f[20][170][170]; int a[20]; dnt dfs(int pos,int sum,int val,int mod,int lim) { dnt ans=0; if(pos==-1) return sum==0&&val==0; if((pos+1)*9<sum) return 0; // 剪枝而已无须在意 if(!lim && f[pos][sum][val]!=-1) return f[pos][sum][val]; int up= lim ? a[pos] : 9; for(int i=0;i<=up;i++) { if(sum<i) break ; ans+=dfs(pos-1,sum-i,(val*10+i)%mod,mod,lim && i==up); } if(!lim) f[pos][sum][val]=ans; return ans; } dnt solve(dnt n) { int cnt=0; dnt ans=0; memset(a,0,sizeof(a)); while(n) { a[cnt++]=n%10; n/=10; } for(int i=1;i<=9*cnt;i++) { memset(f,-1,sizeof(f)); ans+=dfs(cnt-1,i,0,i,1); } return ans; } int main() { dnt a,b; cin >> a >> b; cout << solve(b)-solve(a-1) << endl; return 0; } /* Whoso pulleth out this sword from this stone and anvil is duly born King of all England */
嗯,就是这样
相关文章推荐
- BZOJ 1833 浅谈简单数位动态规划
- BZOJ 1026 浅谈数位动态规划朝花夕拾
- HDU 2089 浅谈数位动态规划水题
- BZOJ 4318 浅谈期望运算性质及期望动态规划
- BZOJ 4720 浅谈期望动态规划状态转移
- BZOJ 2064 浅谈状态压缩动态规划基础及lowbit枚举子集和
- BZOJ 1087 浅谈状态压缩动态规划的转移
- BZOJ 2969 浅谈矩阵期望动态规划面积分布式转移
- BZOJ 4145 浅谈状态压缩动态规划背包问题
- bzoj 1799: [Ahoi2009]self 同类分布(数位DP)
- BZOJ 1799 [Ahoi2009]self 同类分布【数位dp
- [BZOJ1799][Ahoi2009]self 同类分布(数位dp)
- 小白进阶之动态规划-矩阵链乘法
- HDU 4719 浅谈数据结构优化双关键字动态规划
- 浅谈决策单调性在1D1D动态规划中的运用
- 算法进阶之动态规划-01背包问题
- CodeVS 2245 浅谈二维线段树优化间距限制型LCS动态规划状态转移
- bzoj1799[Ahoi2009]self 同类分布 【数位dp】
- 动态规划晋级——HDU 3555 Bomb【数位DP详解】
- 浅谈算法之动态规划