• [数位DP][记忆化搜索]JZOJ 3316 非回文数字


    Description

    如果一个字符串从后往前读与从前往后读一致,我们则称之为回文字符串。当一个数字不包含长度大于1的子回文数字时称为非回文数字。例如,16276是非回文数字,但17276不是,因为它包含回文数字727。

    你的任务是在一个给定的范围内计算非回文数字的总数。
     

    Input

    输入仅一行,包含两个整数a和b。

    Output

    输出仅一行,包含一个整数,表示a到b范围内(包括a和b)非回文数字的总数。
     

    Sample Input

    输入1:
    123 321
    输入2:
    123456789 987654321

    Sample Output

    输出1:
    153
    输出2:
    167386971
     

    Data Constraint

    25%的数据:b-a<=100 000.

    100%的数据:0<=a<=b<=10^18

    分析

    带限制求两数中总数,较显然是数位DP

    我们考虑,如果第i位与其i-1位和i-2位都不相同,那么这个数是非回文子树

    那么我们设f[i][j][k][l]表示做到第i位,i-2位为j,i-1位为k,是否在边界上

    但是我们必须注意特殊的状况:前导零

    那么我们设多两位状态[zero2][zero1]表示i-2位是否前导零,i-1位是否前导零,对于前导零不需要进行回文的判断

    数位DP的递推好恶心啊

    记忆化搜索即可

    #include <iostream>
    #include <cstdio>
    #include <memory.h>
    using namespace std;
    typedef long long ll;
    ll a,ans;
    ll f[20][10][10][2][2][2];
    int c[20],len;
    
    ll Calc(int dep,int pre2,int pre1,bool zero2,bool zero1,bool limit) {
        if (f[dep][pre2][pre1][zero2][zero1][limit]>=0) return f[dep][pre2][pre1][zero2][zero1][limit];
        ll ans=0;
        if (dep>len) return 1;
        if (limit) {
            for (int i=0;i<=c[dep];i++)
                if ((zero2||i!=pre2)&&(zero1||i!=pre1))
                    ans+=Calc(dep+1,pre1,i,zero1,zero1&&(i==0),i==c[dep]);
        }
        else {
            for (int i=0;i<=9;i++)
                if ((zero2||i!=pre2)&&(zero1||i!=pre1))
                    ans+=Calc(dep+1,pre1,i,zero1,zero1&&(i==0),0);
        }
        return f[dep][pre2][pre1][zero2][zero1][limit]=ans;
    }
    
    ll Solve(ll x) {
        if (x<0) return 0;
        len=0;memset(f,-1,sizeof f);
        while (x) c[++len]=x%10,x/=10;
        for (int i=1;i<=len/2;i++) swap(c[i],c[len-i+1]);
        return Calc(1,0,0,1,1,1);
    }
    
    int main() {
        scanf("%lld",&a);a--;
        ans-=Solve(a);
        scanf("%lld",&a);
        ans+=Solve(a);
        printf("%lld",ans);
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    经典排序——希尔排序
    经典排序——插入排序
    使用Ajax验证用户名是否存在
    样式小记
    JavaScript学习笔记(二)
    SpringBoot访问静态视图的两种方式
    扩展SpringMVC-Configuration
    ViewResolver -Springboot中的视图解析器
    SpringBoot必知必会-yaml基础语法
    IDE 下载资源整理
  • 原文地址:https://www.cnblogs.com/mastervan/p/11136076.html
Copyright © 2020-2023  润新知