数位DP小结


数位DP递归版的基本模式。

数位DP经常询问的是在某个区间内符合某种条件的个数。

我个人喜欢用递归,因为简单好些。

先给个基本模式。

hdu 2089 不要62

http://acm.hdu.edu.cn/showproblem.php?pid=2089

询问区间中不包含4和62的个数。

#include<cstring>
#include<cstdio>
#include<iostream>
#define FOR(i,a,b) for(int i=a;i<=b;++i)
#define clr(f,z) memset(f,z,sizeof(f))
using namespace std;
const int mm=11;
int dp[mm][mm][2];///位数,last num,has contain bad num
int bit[mm];
int DP(int pp,int last,bool has,bool big)
{
  if(pp==-1)return has==0;///no contain bad num
  if(big&&dp[pp][last][has]!=-1)return dp[pp][last][has];
  int ret=0;
  int kn=big?9:bit[pp];
  FOR(i,0,kn)
  {
   ret+=DP(pp-1,i,has||(i==4||(last==6&&i==2)),big||kn!=i);
  }
  if(big)dp[pp][last][has]=ret;
  return ret;
}
int get(int x)
{
 int pos=-1;
 while(x)
 {
  bit[++pos]=x%10;x/=10;
 }
 return DP(pos,0,0,0);
}
int main()
{
 clr(dp,-1);
 int n,m;
 while(cin>>n>>m)
 { if(n==0&&m==0)break;
  cout<<get(m)-get(n-1)<<endl;
 }
}

大体的数位DP 都可以套用以上的形式来写。

其中状态有个注意点,就是设计的DP 状态能不能适用于所有的分组数据,如果可以就只需要初始化一次,如果不行,那每次执行都需要初始化。

比如: 

hdu 4734 F(x)(数位

DP,4级)

如果设计状态是dp[bit][statue] 表示i位长,能达到值为statue 的最优值,那就得每次初始化,那就T 了,因为每次询问所要求小于的数都不一样。

但如果换一个表式就可以了,表示bit位长,比statue小的有多少个,那就满足所有的询问了,就只需要初始化一次。

具体看这

http://blog.csdn.net/nealgavin/article/details/11703049

/***********************************************************************************************/

然后:数位DP 最重要的就赛状态设计和,一些状态精简之类的问题了。

《1.》 像这一题就是和LCM有关的数位DP 。

CodeForces 55D Beautiful numbers (数位DP+状态简化,5级)

http://blog.csdn.net/nealgavin/article/details/10446739

很容易能想到三维DP dp[第几位][模上最小公倍数数的余数][最小公倍数]

          最小公倍数到2520 为止 ,故 需要 19x2520x2520 爆空间了。

         但实际上能取到的最小公倍数没有2520个,只要几十个,因此可以哈希一下,因为DP只要记录其不同状态就可以了。

        dp不需要每个数都算原因是不同数的mod数不同。因此不会错

         接下来,就是水数位DP了。

《2.》SPOJ 10606. Balanced Numbers (数位DP,4级)

http://blog.csdn.net/nealgavin/article/details/10335221

《3.》这道是好题。状态压缩的递增自序列数位DP ,如果都理解透的化也是可以秒的。

 

hdu 4352 XHXJ's LIS(LIS+数位DP,5级)


http://blog.csdn.net/nealgavin/article/details/10078027

《4.》这到题就需要理解数位DP,它到底在求的是什么。

hdu 3709 Balanced Number(数位DP,5级)

http://blog.csdn.net/nealgavin/article/details/10084467

《5.》好题,需要设计多种状态,要分清楚。 

hdu 4507 吉哥系列故事——恨7不成妻(数位DP,5级)

http://blog.csdn.net/nealgavin/article/details/10095879

思路:维护3个值,个数,总和,平方和。
          第一个是与7无关的数的个数,就是简单的数位DP了,很常规
          第二个与7无关的数的和的维护需要用到第一个个数。
           处理到第pos个数位时,加上i*10^pos * 后面的个数
          第三个的维护需要用到前面两个
          (pre*10^pos + next)^2= (pre*10^pos)^2+2*pre*10^pos*next +next^2

《6.》同样是道好题,AC自动机+数位DP 。要先用AC自动机先预处理出所有的转移态,然后数位DP 转移态

 

ZOJ 3494 BCD Code (AC自动机+数位DP,5级)


http://blog.csdn.net/nealgavin/article/details/10303521



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值