【数位DP】HDU2089[不要62]题解

题目概述

[L,R] 中子串不含有 62 4 的数的个数。

解题报告

感觉重学了一遍数位DP……定义 f[i][0/1] 表示合法且末尾不为 2 /合法且末尾为 2 的方案数。

之前写数位DP我都是枚举贴着 n 的位数,然后每次都刷DP,不仅慢而且有毒……

于是借鉴了一下网上dalao们的写法:先预处理出 f[i][0/1] i 位的所有方案(可以有前导 0 ),然后枚举贴着 n 的位数,用之前预处理的 f[i][0/1] 来统计答案就行了,很巧妙的地方是,位数 <len(n) <script type="math/tex" id="MathJax-Element-13"> n 的位数为 0 的时候统计出来,非常好写。

示例程序

#include<cstdio>
using namespace std;
const int maxn=7;

int L,R,a[maxn+5],f[maxn+5][2]; //1:2 0:other

void Make()
{
    f[0][0]=1;
    for (int i=1;i<=maxn;i++)
    for (int j=0;j<10;j++)
        f[i][j==2]+=(j!=4)*(f[i-1][0]+(j!=6)*f[i-1][1]);
}
inline int Solve(int n)
{
    n++;a[0]=0;do a[++a[0]]=n%10,n/=10; while (n);int ans=0;
    for (int i=a[0],lst=0;i>=1;lst=a[i--])
    {
        int now=a[i]-(a[i]>4)-(lst==6&&a[i]>2);ans+=f[i-1][0]*now;
        now-=a[i]>6;ans+=f[i-1][1]*now;
        if (a[i]==4||lst==6&&a[i]==2) break;
    }
    return ans;
}
int main()
{
    freopen("program.in","r",stdin);
    freopen("program.out","w",stdout);
    for (Make(),scanf("%d%d",&L,&R);L&&R;scanf("%d%d",&L,&R)) printf("%d\n",Solve(R)-Solve(L-1));
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值